Merge branch 'better-belts' into 0.2

This commit is contained in:
simibubi 2019-11-20 22:51:23 +01:00
commit 1e23aa82aa
55 changed files with 3561 additions and 1391 deletions

View file

@ -6,7 +6,7 @@ import com.simibubi.create.modules.IModule;
import com.simibubi.create.modules.contraptions.WrenchItem; import com.simibubi.create.modules.contraptions.WrenchItem;
import com.simibubi.create.modules.contraptions.WrenchItemRenderer; import com.simibubi.create.modules.contraptions.WrenchItemRenderer;
import com.simibubi.create.modules.contraptions.relays.VerticalGearboxItem; import com.simibubi.create.modules.contraptions.relays.VerticalGearboxItem;
import com.simibubi.create.modules.contraptions.relays.belt.BeltItem; import com.simibubi.create.modules.contraptions.relays.belt.BeltConnectorItem;
import com.simibubi.create.modules.curiosities.ChromaticCompoundCubeItem; import com.simibubi.create.modules.curiosities.ChromaticCompoundCubeItem;
import com.simibubi.create.modules.curiosities.deforester.DeforesterItem; import com.simibubi.create.modules.curiosities.deforester.DeforesterItem;
import com.simibubi.create.modules.curiosities.deforester.DeforesterItemRenderer; import com.simibubi.create.modules.curiosities.deforester.DeforesterItemRenderer;
@ -82,7 +82,7 @@ public enum AllItems {
BLUEPRINT(new SchematicItem(standardItemProperties())), BLUEPRINT(new SchematicItem(standardItemProperties())),
__CONTRAPTIONS__(), __CONTRAPTIONS__(),
BELT_CONNECTOR(new BeltItem(standardItemProperties())), BELT_CONNECTOR(new BeltConnectorItem(standardItemProperties())),
VERTICAL_GEARBOX(new VerticalGearboxItem(new Properties())), VERTICAL_GEARBOX(new VerticalGearboxItem(new Properties())),
FLOUR(ingredient()), FLOUR(ingredient()),
DOUGH(ingredient()), DOUGH(ingredient()),

View file

@ -44,6 +44,7 @@ import com.simibubi.create.modules.logistics.block.LinkedTileEntityRenderer;
import com.simibubi.create.modules.logistics.block.RedstoneBridgeTileEntity; import com.simibubi.create.modules.logistics.block.RedstoneBridgeTileEntity;
import com.simibubi.create.modules.logistics.block.StockswitchTileEntity; import com.simibubi.create.modules.logistics.block.StockswitchTileEntity;
import com.simibubi.create.modules.logistics.block.belts.BeltFunnelTileEntity; import com.simibubi.create.modules.logistics.block.belts.BeltFunnelTileEntity;
import com.simibubi.create.modules.logistics.block.belts.BeltFunnelTileEntityRenderer;
import com.simibubi.create.modules.logistics.block.belts.EntityDetectorTileEntity; import com.simibubi.create.modules.logistics.block.belts.EntityDetectorTileEntity;
import com.simibubi.create.modules.logistics.block.belts.EntityDetectorTileEntityRenderer; import com.simibubi.create.modules.logistics.block.belts.EntityDetectorTileEntityRenderer;
import com.simibubi.create.modules.logistics.block.belts.ExtractorTileEntity; import com.simibubi.create.modules.logistics.block.belts.ExtractorTileEntity;
@ -180,6 +181,7 @@ public enum AllTileEntities {
bind(RedstoneBridgeTileEntity.class, new LinkedTileEntityRenderer()); bind(RedstoneBridgeTileEntity.class, new LinkedTileEntityRenderer());
bind(LinkedExtractorTileEntity.class, new LinkedExtractorTileEntityRenderer()); bind(LinkedExtractorTileEntity.class, new LinkedExtractorTileEntityRenderer());
bind(ExtractorTileEntity.class, new ExtractorTileEntityRenderer()); bind(ExtractorTileEntity.class, new ExtractorTileEntityRenderer());
bind(BeltFunnelTileEntity.class, new BeltFunnelTileEntityRenderer());
bind(EntityDetectorTileEntity.class, new EntityDetectorTileEntityRenderer()); bind(EntityDetectorTileEntity.class, new EntityDetectorTileEntityRenderer());
bind(MechanicalPressTileEntity.class, new MechanicalPressTileEntityRenderer()); bind(MechanicalPressTileEntity.class, new MechanicalPressTileEntityRenderer());
bind(FlexpeaterTileEntity.class, new FlexpeaterTileEntityRenderer()); bind(FlexpeaterTileEntity.class, new FlexpeaterTileEntityRenderer());

View file

@ -10,7 +10,7 @@ import com.simibubi.create.foundation.utility.TooltipHelper;
import com.simibubi.create.modules.contraptions.KineticDebugger; import com.simibubi.create.modules.contraptions.KineticDebugger;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.modules.contraptions.receivers.TurntableHandler; import com.simibubi.create.modules.contraptions.receivers.TurntableHandler;
import com.simibubi.create.modules.contraptions.relays.belt.BeltItemHandler; import com.simibubi.create.modules.contraptions.relays.belt.BeltConnectorItemHandler;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
@ -56,7 +56,7 @@ public class ClientEvents {
public static void onGameTick() { public static void onGameTick() {
CreateClient.gameTick(); CreateClient.gameTick();
BeltItemHandler.gameTick(); BeltConnectorItemHandler.gameTick();
} }
@SubscribeEvent @SubscribeEvent

View file

@ -28,7 +28,7 @@ public abstract class SyncedTileEntity extends TileEntity {
} }
public void sendData() { public void sendData() {
world.notifyBlockUpdate(getPos(), getBlockState(), getBlockState(), 2 | 16); world.notifyBlockUpdate(getPos(), getBlockState(), getBlockState(), 2 | 4 | 16);
} }
public void causeBlockUpdate() { public void causeBlockUpdate() {

View file

@ -91,6 +91,19 @@ public abstract class BufferManipulator {
buffer.put(bufferPosition + 15, a); buffer.put(bufferPosition + 15, a);
} }
public ByteBuffer getTranslated(float xIn, float yIn, float zIn, int packedLightCoords) {
original.rewind();
mutable.rewind();
for (int vertex = 0; vertex < vertexCount(original); vertex++) {
putPos(mutable, vertex, getX(original, vertex) + xIn, getY(original, vertex) + yIn,
getZ(original, vertex) + zIn);
putLight(mutable, vertex, packedLightCoords);
}
return mutable;
}
public static ByteBuffer remanipulateBuffer(ByteBuffer buffer, float x, float y, float z, float xOrigin, public static ByteBuffer remanipulateBuffer(ByteBuffer buffer, float x, float y, float z, float xOrigin,
float yOrigin, float zOrigin, float yaw, float pitch) { float yOrigin, float zOrigin, float yaw, float pitch) {
buffer.rewind(); buffer.rewind();

View file

@ -0,0 +1,94 @@
package com.simibubi.create.foundation.utility;
import com.mojang.blaze3d.platform.GlStateManager;
import net.minecraft.block.BlockRenderType;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.IWorldReader;
/**
* Stolen from EntityRenderer
*/
public class IndependentShadowRenderer {
private static final ResourceLocation SHADOW_TEXTURES = new ResourceLocation("textures/misc/shadow.png");
public static void renderShadow(double x, double y, double z, float shadowAlpha, float size) {
GlStateManager.enableBlend();
GlStateManager.enableAlphaTest();
GlStateManager.blendFunc(GlStateManager.SourceFactor.DST_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);
Minecraft.getInstance().getTextureManager().bindTexture(SHADOW_TEXTURES);
IWorldReader iworldreader = Minecraft.getInstance().world;
GlStateManager.depthMask(false);
int i = MathHelper.floor(x - size);
int j = MathHelper.floor(x + size);
int k = MathHelper.floor(y - size);
int l = MathHelper.floor(y);
int i1 = MathHelper.floor(z - size);
int j1 = MathHelper.floor(z + size);
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferbuilder = tessellator.getBuffer();
bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR);
for (BlockPos blockpos : BlockPos.getAllInBoxMutable(new BlockPos(i, k, i1), new BlockPos(j, l, j1))) {
BlockPos blockpos1 = blockpos.down();
BlockState blockstate = iworldreader.getBlockState(blockpos1);
if (blockstate.getRenderType() != BlockRenderType.INVISIBLE && iworldreader.getLight(blockpos) > 3) {
func_217759_a(blockstate, iworldreader, blockpos1, 0, 0, 0, blockpos, shadowAlpha, size, -x, -y, -z);
}
}
tessellator.draw();
GlStateManager.color4f(1.0F, 1.0F, 1.0F, 1.0F);
GlStateManager.disableBlend();
GlStateManager.depthMask(true);
}
private static void func_217759_a(BlockState p_217759_1_, IWorldReader p_217759_2_, BlockPos p_217759_3_,
double p_217759_4_, double p_217759_6_, double p_217759_8_, BlockPos p_217759_10_, float p_217759_11_,
float p_217759_12_, double p_217759_13_, double p_217759_15_, double p_217759_17_) {
ClientWorld world = Minecraft.getInstance().world;
VoxelShape voxelshape = p_217759_1_.getShape(world, p_217759_10_.down());
if (!voxelshape.isEmpty()) {
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferbuilder = tessellator.getBuffer();
double d0 = ((double) p_217759_11_ - (p_217759_6_ - ((double) p_217759_10_.getY() + p_217759_15_)) / 2.0D)
* 0.5D * (double) world.getBrightness(p_217759_10_);
if (!(d0 < 0.0D)) {
if (d0 > 1.0D) {
d0 = 1.0D;
}
AxisAlignedBB axisalignedbb = voxelshape.getBoundingBox();
double d1 = (double) p_217759_10_.getX() + axisalignedbb.minX + p_217759_13_;
double d2 = (double) p_217759_10_.getX() + axisalignedbb.maxX + p_217759_13_;
double d3 = (double) p_217759_10_.getY() + axisalignedbb.minY + p_217759_15_ + 0.015625D;
double d4 = (double) p_217759_10_.getZ() + axisalignedbb.minZ + p_217759_17_;
double d5 = (double) p_217759_10_.getZ() + axisalignedbb.maxZ + p_217759_17_;
float f = (float) ((p_217759_4_ - d1) / 2.0D / (double) p_217759_12_ + 0.5D);
float f1 = (float) ((p_217759_4_ - d2) / 2.0D / (double) p_217759_12_ + 0.5D);
float f2 = (float) ((p_217759_8_ - d4) / 2.0D / (double) p_217759_12_ + 0.5D);
float f3 = (float) ((p_217759_8_ - d5) / 2.0D / (double) p_217759_12_ + 0.5D);
bufferbuilder.pos(d1, d3, d4).tex((double) f, (double) f2).color(1.0F, 1.0F, 1.0F, (float) d0)
.endVertex();
bufferbuilder.pos(d1, d3, d5).tex((double) f, (double) f3).color(1.0F, 1.0F, 1.0F, (float) d0)
.endVertex();
bufferbuilder.pos(d2, d3, d5).tex((double) f1, (double) f3).color(1.0F, 1.0F, 1.0F, (float) d0)
.endVertex();
bufferbuilder.pos(d2, d3, d4).tex((double) f1, (double) f2).color(1.0F, 1.0F, 1.0F, (float) d0)
.endVertex();
}
}
}
}

View file

@ -32,8 +32,7 @@ public class TessellatorHelper {
} }
public static void prepareFastRender() { public static void prepareFastRender() {
Minecraft.getInstance().textureManager Minecraft.getInstance().textureManager.bindTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE);
.bindTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE);
net.minecraft.client.renderer.RenderHelper.disableStandardItemLighting(); net.minecraft.client.renderer.RenderHelper.disableStandardItemLighting();
GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GlStateManager.enableBlend(); GlStateManager.enableBlend();
@ -131,10 +130,12 @@ public class TessellatorHelper {
if (doubleFaces) { if (doubleFaces) {
TessellatorHelper.doubleFace(bufferBuilder, pos, new BlockPos(w, 0, l), scale, true, scaleVertical, false); TessellatorHelper.doubleFace(bufferBuilder, pos, new BlockPos(w, 0, l), scale, true, scaleVertical, false);
TessellatorHelper.doubleFace(bufferBuilder, pos.east(w).up(h), new BlockPos(-w, 0, l), scale, true, scaleVertical, false); TessellatorHelper.doubleFace(bufferBuilder, pos.east(w).up(h), new BlockPos(-w, 0, l), scale, true,
scaleVertical, false);
} else { } else {
TessellatorHelper.face(bufferBuilder, pos, new BlockPos(w, 0, l), scale, true, scaleVertical, false, false); TessellatorHelper.face(bufferBuilder, pos, new BlockPos(w, 0, l), scale, true, scaleVertical, false, false);
TessellatorHelper.face(bufferBuilder, pos.east(w).up(h), new BlockPos(-w, 0, l), scale, true, scaleVertical, false, false); TessellatorHelper.face(bufferBuilder, pos.east(w).up(h), new BlockPos(-w, 0, l), scale, true, scaleVertical,
false, false);
} }
} }
@ -146,13 +147,17 @@ public class TessellatorHelper {
if (doubleFaces) { if (doubleFaces) {
TessellatorHelper.doubleFace(bufferBuilder, pos, new BlockPos(w, h, 0), scale, true, scaleVertical, false); TessellatorHelper.doubleFace(bufferBuilder, pos, new BlockPos(w, h, 0), scale, true, scaleVertical, false);
TessellatorHelper.doubleFace(bufferBuilder, pos.east(w).south(l), new BlockPos(0, h, -l), scale, true, scaleVertical, false); TessellatorHelper.doubleFace(bufferBuilder, pos.east(w).south(l), new BlockPos(0, h, -l), scale, true,
TessellatorHelper.doubleFace(bufferBuilder, pos.east(w).south(l), new BlockPos(-w, h, 0), scale, true, scaleVertical, false); scaleVertical, false);
TessellatorHelper.doubleFace(bufferBuilder, pos.east(w).south(l), new BlockPos(-w, h, 0), scale, true,
scaleVertical, false);
TessellatorHelper.doubleFace(bufferBuilder, pos, new BlockPos(0, h, l), scale, true, scaleVertical, false); TessellatorHelper.doubleFace(bufferBuilder, pos, new BlockPos(0, h, l), scale, true, scaleVertical, false);
} else { } else {
TessellatorHelper.face(bufferBuilder, pos, new BlockPos(w, h, 0), scale, true, scaleVertical, false, false); TessellatorHelper.face(bufferBuilder, pos, new BlockPos(w, h, 0), scale, true, scaleVertical, false, false);
TessellatorHelper.face(bufferBuilder, pos.east(w).south(l), new BlockPos(0, h, -l), scale, true, scaleVertical, false, false); TessellatorHelper.face(bufferBuilder, pos.east(w).south(l), new BlockPos(0, h, -l), scale, true,
TessellatorHelper.face(bufferBuilder, pos.east(w).south(l), new BlockPos(-w, h, 0), scale, true, scaleVertical, false, false); scaleVertical, false, false);
TessellatorHelper.face(bufferBuilder, pos.east(w).south(l), new BlockPos(-w, h, 0), scale, true,
scaleVertical, false, false);
TessellatorHelper.face(bufferBuilder, pos, new BlockPos(0, h, l), scale, true, scaleVertical, false, false); TessellatorHelper.face(bufferBuilder, pos, new BlockPos(0, h, l), scale, true, scaleVertical, false, false);
} }
} }

View file

@ -3,11 +3,15 @@ package com.simibubi.create.foundation.utility;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.apache.commons.lang3.mutable.MutableObject;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Direction.AxisDirection;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.util.math.shapes.VoxelShapes;
public class VoxelShaper { public class VoxelShaper {
@ -17,7 +21,11 @@ public class VoxelShaper {
return shapes.get(direction); return shapes.get(direction);
} }
public static VoxelShaper forHorizontalBlock(VoxelShape southShape) { public VoxelShape get(Axis axis) {
return shapes.get(axisAsFace(axis));
}
public static VoxelShaper forHorizontal(VoxelShape southShape) {
VoxelShaper voxelShaper = new VoxelShaper(); VoxelShaper voxelShaper = new VoxelShaper();
for (Direction facing : Direction.values()) { for (Direction facing : Direction.values()) {
if (facing.getAxis().isVertical()) if (facing.getAxis().isVertical())
@ -27,7 +35,27 @@ public class VoxelShaper {
return voxelShaper; return voxelShaper;
} }
public static VoxelShaper forDirectionalBlock(VoxelShape southShape) { public static VoxelShaper forHorizontalAxis(VoxelShape zShape) {
VoxelShaper voxelShaper = new VoxelShaper();
for (Axis axis : Axis.values()) {
if (axis.isVertical())
continue;
Direction facing = axisAsFace(axis);
voxelShaper.shapes.put(facing, rotatedCopy(zShape, 0, (int) -facing.getHorizontalAngle()));
}
return voxelShaper;
}
public static VoxelShaper forRotatedPillar(VoxelShape zShape) {
VoxelShaper voxelShaper = new VoxelShaper();
for (Axis axis : Axis.values()) {
Direction facing = axisAsFace(axis);
voxelShaper.shapes.put(facing, rotatedCopy(zShape, 0, (int) -facing.getHorizontalAngle()));
}
return voxelShaper;
}
public static VoxelShaper forDirectional(VoxelShape southShape) {
VoxelShaper voxelShaper = new VoxelShaper(); VoxelShaper voxelShaper = new VoxelShaper();
for (Direction facing : Direction.values()) { for (Direction facing : Direction.values()) {
int rotX = facing.getAxis().isVertical() ? (facing == Direction.UP ? 270 : 90) : 0; int rotX = facing.getAxis().isVertical() ? (facing == Direction.UP ? 270 : 90) : 0;
@ -43,19 +71,28 @@ public class VoxelShaper {
return this; return this;
} }
public static VoxelShape rotatedCopy(VoxelShape shape, int rotX, int rotY) { private static Direction axisAsFace(Axis axis) {
return Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis);
}
private static VoxelShape rotatedCopy(VoxelShape shape, int rotX, int rotY) {
MutableObject<VoxelShape> result = new MutableObject<>(VoxelShapes.empty());
shape.forEachBox((x1, y1, z1, x2, y2, z2) -> {
Vec3d center = new Vec3d(8, 8, 8); Vec3d center = new Vec3d(8, 8, 8);
Vec3d v1 = new Vec3d(shape.getStart(Axis.X), shape.getStart(Axis.Y), shape.getStart(Axis.Z)).scale(16) Vec3d v1 = new Vec3d(x1, y1, z1).scale(16).subtract(center);
.subtract(center); Vec3d v2 = new Vec3d(x2, y2, z2).scale(16).subtract(center);
Vec3d v2 = new Vec3d(shape.getEnd(Axis.X), shape.getEnd(Axis.Y), shape.getEnd(Axis.Z)).scale(16)
.subtract(center);
v1 = VecHelper.rotate(v1, rotX, Axis.X); v1 = VecHelper.rotate(v1, rotX, Axis.X);
v1 = VecHelper.rotate(v1, rotY, Axis.Y).add(center); v1 = VecHelper.rotate(v1, rotY, Axis.Y).add(center);
v2 = VecHelper.rotate(v2, rotX, Axis.X); v2 = VecHelper.rotate(v2, rotX, Axis.X);
v2 = VecHelper.rotate(v2, rotY, Axis.Y).add(center); v2 = VecHelper.rotate(v2, rotY, Axis.Y).add(center);
return Block.makeCuboidShape(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z); VoxelShape rotated = Block.makeCuboidShape(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z);
result.setValue(VoxelShapes.or(result.getValue(), rotated));
});
return result.getValue();
} }
} }

View file

@ -5,6 +5,6 @@ import net.minecraft.block.Block;
public class VoxelShapers { public class VoxelShapers {
public static final VoxelShaper SHORT_CASING = VoxelShaper public static final VoxelShaper SHORT_CASING = VoxelShaper
.forDirectionalBlock(Block.makeCuboidShape(0, 0, 0, 16, 16, 12)); .forDirectional(Block.makeCuboidShape(0, 0, 0, 16, 16, 12));
} }

View file

@ -5,6 +5,7 @@ import com.simibubi.create.foundation.utility.ColoredIndicatorRenderer;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.modules.contraptions.receivers.constructs.ContraptionRenderer; import com.simibubi.create.modules.contraptions.receivers.constructs.ContraptionRenderer;
import com.simibubi.create.modules.contraptions.receivers.constructs.MechanicalBearingTileEntityRenderer; import com.simibubi.create.modules.contraptions.receivers.constructs.MechanicalBearingTileEntityRenderer;
import com.simibubi.create.modules.contraptions.relays.belt.BeltModelAnimator;
import net.minecraft.client.resources.ReloadListener; import net.minecraft.client.resources.ReloadListener;
import net.minecraft.profiler.IProfiler; import net.minecraft.profiler.IProfiler;
@ -24,6 +25,7 @@ public class CachedBufferReloader extends ReloadListener<String> {
MechanicalBearingTileEntityRenderer.invalidateCache(); MechanicalBearingTileEntityRenderer.invalidateCache();
ColoredIndicatorRenderer.invalidateCache(); ColoredIndicatorRenderer.invalidateCache();
CTModelTextureHandler.reloadUVs(); CTModelTextureHandler.reloadUVs();
BeltModelAnimator.invalidateCache();
} }

View file

@ -2,7 +2,6 @@ package com.simibubi.create.modules.contraptions;
import static com.simibubi.create.AllBlocks.BELT; import static com.simibubi.create.AllBlocks.BELT;
import static com.simibubi.create.AllBlocks.COGWHEEL; import static com.simibubi.create.AllBlocks.COGWHEEL;
import static com.simibubi.create.AllBlocks.ENCASED_FAN;
import static com.simibubi.create.AllBlocks.LARGE_COGWHEEL; import static com.simibubi.create.AllBlocks.LARGE_COGWHEEL;
import static com.simibubi.create.CreateConfig.parameters; import static com.simibubi.create.CreateConfig.parameters;
import static net.minecraft.state.properties.BlockStateProperties.AXIS; import static net.minecraft.state.properties.BlockStateProperties.AXIS;
@ -76,12 +75,6 @@ public class RotationPropagator {
return connected ? 1 : 0; return connected ? 1 : 0;
} }
// Attached Fans
if (ENCASED_FAN.typeOf(stateFrom) && ENCASED_FAN.typeOf(stateTo)) {
if (stateFrom.get(AXIS) == stateTo.get(AXIS))
return 1;
}
// Large Gear <-> Large Gear // Large Gear <-> Large Gear
if (isLargeToLargeGear(stateFrom, stateTo, diff)) { if (isLargeToLargeGear(stateFrom, stateTo, diff)) {
Axis sourceAxis = stateFrom.get(AXIS); Axis sourceAxis = stateFrom.get(AXIS);

View file

@ -34,7 +34,7 @@ import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
@EventBusSubscriber(value = Dist.CLIENT) @EventBusSubscriber(value = Dist.CLIENT)
public class KineticTileEntityRenderer extends TileEntityRendererFast<KineticTileEntity> { public class KineticTileEntityRenderer extends TileEntityRendererFast<KineticTileEntity> {
protected static Map<BlockState, BufferManipulator> cachedBuffers; public static Map<BlockState, BufferManipulator> cachedBuffers;
public static boolean rainbowMode = false; public static boolean rainbowMode = false;
public static class BlockModelSpinner extends BufferManipulator { public static class BlockModelSpinner extends BufferManipulator {

View file

@ -0,0 +1,71 @@
package com.simibubi.create.modules.contraptions.receivers;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.logistics.InWorldProcessing;
import com.simibubi.create.modules.logistics.InWorldProcessing.Type;
import net.minecraft.particles.ParticleTypes;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
public class EncasedFanBeltHandler {
// Fans need to be aware of belt TEs within their range
// all belts are handled equally
// requires ref to controller and index
static List<BeltTileEntity> findBelts(EncasedFanTileEntity fan) {
if (fan.getSpeed() == 0)
return Collections.emptyList();
List<BeltTileEntity> belts = new ArrayList<>();
AxisAlignedBB searchBB = fan.frontBB.shrink(.25).contract(0, 0, 0).expand(0, -.25f, 0);
BlockPos.getAllInBox((int) searchBB.minX, (int) searchBB.minY, (int) searchBB.minZ, (int) searchBB.maxX - 1,
(int) searchBB.maxY - 1, (int) searchBB.maxZ - 1)
.filter(p -> AllBlocks.BELT.typeOf(fan.getWorld().getBlockState(p))).forEach(p -> {
TileEntity te = fan.getWorld().getTileEntity(p);
if (te == null || !(te instanceof BeltTileEntity))
return;
belts.add((BeltTileEntity) te);
});
return belts;
}
static void tickBelts(EncasedFanTileEntity fan, List<BeltTileEntity> belts) {
Type processingType = fan.getProcessingType();
if (processingType == null)
return;
for (BeltTileEntity belt : belts) {
BeltTileEntity controller = belt.getControllerTE();
if (controller == null)
continue;
World world = belt.getWorld();
controller.getInventory().forEachWithin(belt.index + .5f, .5f, (transported) -> {
if (world.rand.nextInt(4) == 0 && world.isRemote) {
Vec3d vec = controller.getInventory().getVectorForOffset(transported.beltPosition);
if (processingType == Type.BLASTING)
world.addParticle(ParticleTypes.LARGE_SMOKE, vec.x, vec.y + .25f, vec.z, 0, 1 / 16f, 0);
if (processingType == Type.SMOKING)
world.addParticle(ParticleTypes.CLOUD, vec.x, vec.y + .25f, vec.z, 0, 1 / 16f, 0);
if (processingType == Type.SPLASHING)
world.addParticle(ParticleTypes.BUBBLE_POP, vec.x + (world.rand.nextFloat() - .5f) * .5f,
vec.y + .25f, vec.z + (world.rand.nextFloat() - .5f) * .5f, 0, 1 / 16f, 0);
}
if (world.isRemote)
return null;
return InWorldProcessing.applyProcessing(transported, belt, processingType);
});
}
}
}

View file

@ -26,7 +26,7 @@ public class EncasedFanParticleHandler {
private void initEffects() { private void initEffects() {
List<FanEffect> standardFX = new ArrayList<>(2); List<FanEffect> standardFX = new ArrayList<>(2);
standardFX.add(new FanEffect(ParticleTypes.BUBBLE_POP, 1 / 4f, 1 / 4f, 1 / 3f, 1)); standardFX.add(new FanEffect(ParticleTypes.BUBBLE_POP, 1 / 4f, 1 / 4f, 1 / 8f, 1));
standardFX.add(new FanEffect(new RedstoneParticleData(1, 1, 1, 1), 1 / 2f, 1 / 32f, 1/16f, 512f)); standardFX.add(new FanEffect(new RedstoneParticleData(1, 1, 1, 1), 1 / 2f, 1 / 32f, 1/16f, 512f));
effects.put(Blocks.AIR, standardFX); effects.put(Blocks.AIR, standardFX);

View file

@ -5,6 +5,7 @@ import static net.minecraft.state.properties.BlockStateProperties.AXIS;
import static net.minecraft.util.Direction.AxisDirection.NEGATIVE; import static net.minecraft.util.Direction.AxisDirection.NEGATIVE;
import static net.minecraft.util.Direction.AxisDirection.POSITIVE; import static net.minecraft.util.Direction.AxisDirection.POSITIVE;
import java.util.Collections;
import java.util.List; import java.util.List;
import com.simibubi.create.AllBlockTags; import com.simibubi.create.AllBlockTags;
@ -14,6 +15,7 @@ import com.simibubi.create.CreateClient;
import com.simibubi.create.CreateConfig; import com.simibubi.create.CreateConfig;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.base.GeneratingKineticTileEntity; import com.simibubi.create.modules.contraptions.base.GeneratingKineticTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.logistics.InWorldProcessing; import com.simibubi.create.modules.logistics.InWorldProcessing;
import com.simibubi.create.modules.logistics.InWorldProcessing.Type; import com.simibubi.create.modules.logistics.InWorldProcessing.Type;
@ -51,6 +53,7 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity {
protected boolean findFrontBlock; protected boolean findFrontBlock;
protected BlockState frontBlock; protected BlockState frontBlock;
protected boolean isGenerator; protected boolean isGenerator;
protected List<BeltTileEntity> affectedBelts = Collections.emptyList();
public EncasedFanTileEntity() { public EncasedFanTileEntity() {
super(AllTileEntities.ENCASED_FAN.type); super(AllTileEntities.ENCASED_FAN.type);
@ -67,6 +70,7 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity {
super.readClientUpdate(tag); super.readClientUpdate(tag);
updateFrontBlock(); updateFrontBlock();
updateBBs(); updateBBs();
affectedBelts = EncasedFanBeltHandler.findBelts(this);
} }
@Override @Override
@ -140,6 +144,7 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity {
backBB = new AxisAlignedBB(0, 0, 0, 0, 0, 0); backBB = new AxisAlignedBB(0, 0, 0, 0, 0, 0);
} }
affectedBelts = EncasedFanBeltHandler.findBelts(this);
sendData(); sendData();
} }
@ -190,6 +195,8 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity {
if (getSpeed() == 0 || isGenerator) if (getSpeed() == 0 || isGenerator)
return; return;
EncasedFanBeltHandler.tickBelts(this, affectedBelts);
List<Entity> frontEntities = world.getEntitiesWithinAABBExcludingEntity(null, frontBB); List<Entity> frontEntities = world.getEntitiesWithinAABBExcludingEntity(null, frontBB);
for (Entity entity : frontEntities) { for (Entity entity : frontEntities) {
moveEntity(entity, true); moveEntity(entity, true);
@ -238,7 +245,7 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity {
return; return;
if (canProcess((ItemEntity) entity)) if (canProcess((ItemEntity) entity))
InWorldProcessing.process((ItemEntity) entity, getProcessingType()); InWorldProcessing.applyProcessing((ItemEntity) entity, getProcessingType());
} else { } else {
if (getProcessingType() == Type.SMOKING) { if (getProcessingType() == Type.SMOKING) {

View file

@ -39,7 +39,7 @@ import net.minecraftforge.common.IPlantable;
public class HarvesterBlock extends HorizontalBlock implements IHaveMovementBehavior { public class HarvesterBlock extends HorizontalBlock implements IHaveMovementBehavior {
private static VoxelShaper SHAPER = VoxelShaper.forHorizontalBlock(Block.makeCuboidShape(0, 2, 0, 16, 14, 3)); private static VoxelShaper SHAPER = VoxelShaper.forHorizontal(Block.makeCuboidShape(0, 2, 0, 16, 14, 3));
public HarvesterBlock() { public HarvesterBlock() {
super(Properties.from(Blocks.IRON_BLOCK)); super(Properties.from(Blocks.IRON_BLOCK));

View file

@ -7,21 +7,22 @@ import java.util.Optional;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.block.IRenderUtilityBlock; import com.simibubi.create.foundation.block.IRenderUtilityBlock;
import com.simibubi.create.foundation.block.IWithTileEntity; import com.simibubi.create.foundation.block.IWithTileEntity;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.block.SyncedTileEntity;
import com.simibubi.create.foundation.utility.ItemHelper;
import com.simibubi.create.modules.contraptions.base.HorizontalKineticBlock; import com.simibubi.create.modules.contraptions.base.HorizontalKineticBlock;
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.BeltAttachmentState; import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.BeltAttachmentState;
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.IBeltAttachment; import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.IBeltAttachment;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity; import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.TransportedItemStack;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.block.HorizontalBlock; import net.minecraft.block.HorizontalBlock;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemStack;
import net.minecraft.state.StateContainer.Builder; import net.minecraft.state.StateContainer.Builder;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
@ -99,8 +100,8 @@ public class MechanicalPressBlock extends HorizontalKineticBlock
} }
@Override @Override
public List<BlockPos> getPotentialAttachmentLocations(BeltTileEntity te) { public List<BlockPos> getPotentialAttachmentPositions(IWorld world, BlockPos pos, BlockState beltState) {
return Arrays.asList(te.getPos().up(2)); return Arrays.asList(pos.up(2));
} }
@Override @Override
@ -112,15 +113,35 @@ public class MechanicalPressBlock extends HorizontalKineticBlock
} }
@Override @Override
public Optional<BlockPos> getValidBeltPositionFor(IWorld world, BlockPos pos, BlockState state) { public BlockPos getBeltPositionForAttachment(IWorld world, BlockPos pos, BlockState state) {
BlockState blockState = world.getBlockState(pos.down(2)); return pos.down(2);
if (!AllBlocks.BELT.typeOf(blockState) || blockState.get(BeltBlock.SLOPE) != Slope.HORIZONTAL)
return Optional.empty();
return Optional.of(pos.down(2));
} }
@Override @Override
public boolean handleEntity(BeltTileEntity te, Entity entity, BeltAttachmentState state) { public boolean isAttachedCorrectly(IWorld world, BlockPos attachmentPos, BlockPos beltPos,
BlockState attachmentState, BlockState beltState) {
return AllBlocks.BELT.typeOf(beltState) && beltState.get(BeltBlock.SLOPE) == Slope.HORIZONTAL;
}
@Override
public boolean startProcessingItem(BeltTileEntity te, TransportedItemStack transported, BeltAttachmentState state) {
MechanicalPressTileEntity pressTe = (MechanicalPressTileEntity) te.getWorld()
.getTileEntity(state.attachmentPos);
if (pressTe == null || pressTe.getSpeed() == 0)
return false;
if (pressTe.running)
return false;
if (!pressTe.getRecipe(transported.stack).isPresent())
return false;
state.processingDuration = 1;
pressTe.start(true);
return true;
}
@Override
public boolean processItem(BeltTileEntity te, TransportedItemStack transportedStack, BeltAttachmentState state) {
MechanicalPressTileEntity pressTe = (MechanicalPressTileEntity) te.getWorld() MechanicalPressTileEntity pressTe = (MechanicalPressTileEntity) te.getWorld()
.getTileEntity(state.attachmentPos); .getTileEntity(state.attachmentPos);
@ -128,42 +149,23 @@ public class MechanicalPressBlock extends HorizontalKineticBlock
if (pressTe == null || pressTe.getSpeed() == 0) if (pressTe == null || pressTe.getSpeed() == 0)
return false; return false;
// Not an Item
if (!(entity instanceof ItemEntity))
return false;
// Running // Running
if (pressTe.running) { if (pressTe.running) {
double distanceTo = entity.getPositionVec().distanceTo(VecHelper.getCenterOf(te.getPos())); if (pressTe.runningTicks == 30) {
if (distanceTo < .32f) Optional<PressingRecipe> recipe = pressTe.getRecipe(transportedStack.stack);
if (!recipe.isPresent())
return false;
ItemStack out = recipe.get().getRecipeOutput().copy();
List<ItemStack> multipliedOutput = ItemHelper.multipliedOutput(transportedStack.stack, out);
if (multipliedOutput.isEmpty())
transportedStack.stack = ItemStack.EMPTY;
transportedStack.stack = multipliedOutput.get(0);
TileEntity controllerTE = te.getWorld().getTileEntity(te.getController());
if (controllerTE != null && controllerTE instanceof BeltTileEntity)
((SyncedTileEntity) controllerTE).sendData();
}
return true; return true;
if (distanceTo < .4f) {
entity.setPosition(te.getPos().getX() + .5f, entity.posY, te.getPos().getZ() + .5f);
return true;
}
return false;
}
// Start process
if (state.processingEntity != entity) {
state.processingEntity = entity;
if (!pressTe.getRecipe((ItemEntity) entity).isPresent()) {
state.processingDuration = -1;
} else {
state.processingDuration = 1;
pressTe.start(true);
}
return false;
}
// Already processed
if (state.processingDuration == -1)
return false;
// Just Finished
if (pressTe.finished) {
state.processingDuration = -1;
return false;
} }
return false; return false;

View file

@ -6,13 +6,17 @@ import com.simibubi.create.AllRecipes;
import com.simibubi.create.AllTileEntities; import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity; import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.TransportedItemStack;
import com.simibubi.create.modules.logistics.InWorldProcessing; import com.simibubi.create.modules.logistics.InWorldProcessing;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.item.ItemEntity; import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.particles.ItemParticleData; import net.minecraft.particles.ItemParticleData;
import net.minecraft.particles.ParticleTypes; import net.minecraft.particles.ParticleTypes;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvents; import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.AxisAlignedBB;
@ -90,26 +94,40 @@ public class MechanicalPressTileEntity extends KineticTileEntity {
return; return;
if (runningTicks == 30) { if (runningTicks == 30) {
if (!beltMode) {
AxisAlignedBB bb = new AxisAlignedBB(pos.down(beltMode ? 2 : 1)); AxisAlignedBB bb = new AxisAlignedBB(pos.down(beltMode ? 2 : 1));
for (Entity entity : world.getEntitiesWithinAABBExcludingEntity(null, bb)) { for (Entity entity : world.getEntitiesWithinAABBExcludingEntity(null, bb)) {
if (!(entity instanceof ItemEntity)) if (!(entity instanceof ItemEntity))
continue; continue;
ItemEntity itemEntity = (ItemEntity) entity;
if (world.isRemote) { ItemEntity itemEntity = (ItemEntity) entity;
for (int i = 0; i < 20; i++) { makeParticleEffect(entity.getPositionVec(), itemEntity.getItem());
Vec3d motion = VecHelper.offsetRandomly(Vec3d.ZERO, world.rand, .25f).mul(1, 0, 1);
world.addParticle(new ItemParticleData(ParticleTypes.ITEM, itemEntity.getItem()), entity.posX,
entity.posY, entity.posZ, motion.x, motion.y, motion.z);
}
}
if (!world.isRemote) { if (!world.isRemote) {
Optional<PressingRecipe> recipe = getRecipe(itemEntity); Optional<PressingRecipe> recipe = getRecipe(itemEntity.getItem());
if (recipe.isPresent()) if (recipe.isPresent())
InWorldProcessing.applyRecipeOn(itemEntity, recipe.get()); InWorldProcessing.applyRecipeOn(itemEntity, recipe.get());
} }
} }
}
if (beltMode && world.isRemote) {
TileEntity te = world.getTileEntity(pos.down(2));
if (te != null && te instanceof BeltTileEntity) {
BeltTileEntity beltTE = (BeltTileEntity) te;
TileEntity controller = world.getTileEntity(beltTE.getController());
if (controller != null && controller instanceof BeltTileEntity) {
TransportedItemStack stackAtOffset = ((BeltTileEntity) controller).getInventory()
.getStackAtOffset(beltTE.index);
if (stackAtOffset != null)
makeParticleEffect(VecHelper.getCenterOf(pos.down(2)).add(0, 5 / 16f, 0),
stackAtOffset.stack);
}
}
}
if (!world.isRemote) { if (!world.isRemote) {
world.playSound(null, getPos(), SoundEvents.ENTITY_ITEM_BREAK, SoundCategory.BLOCKS, .5f, 1f); world.playSound(null, getPos(), SoundEvents.ENTITY_ITEM_BREAK, SoundCategory.BLOCKS, .5f, 1f);
world.playSound(null, getPos(), SoundEvents.BLOCK_ANVIL_LAND, SoundCategory.BLOCKS, .125f, 1f); world.playSound(null, getPos(), SoundEvents.BLOCK_ANVIL_LAND, SoundCategory.BLOCKS, .125f, 1f);
@ -128,8 +146,18 @@ public class MechanicalPressTileEntity extends KineticTileEntity {
runningTicks++; runningTicks++;
} }
public Optional<PressingRecipe> getRecipe(ItemEntity itemEntity) { public void makeParticleEffect(Vec3d pos, ItemStack stack) {
pressingInv.setInventorySlotContents(0, itemEntity.getItem()); if (world.isRemote) {
for (int i = 0; i < 20; i++) {
Vec3d motion = VecHelper.offsetRandomly(Vec3d.ZERO, world.rand, .25f).mul(1, 0, 1);
world.addParticle(new ItemParticleData(ParticleTypes.ITEM, stack), pos.x, pos.y, pos.z, motion.x,
motion.y, motion.z);
}
}
}
public Optional<PressingRecipe> getRecipe(ItemStack item) {
pressingInv.setInventorySlotContents(0, item);
Optional<PressingRecipe> recipe = world.getRecipeManager().getRecipe(AllRecipes.Types.PRESSING, pressingInv, Optional<PressingRecipe> recipe = world.getRecipeManager().getRecipe(AllRecipes.Types.PRESSING, pressingInv,
world); world);
return recipe; return recipe;

View file

@ -4,10 +4,11 @@ import net.minecraft.inventory.ItemStackHelper;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.NonNullList; import net.minecraft.util.NonNullList;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemStackHandler; import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.items.wrapper.RecipeWrapper; import net.minecraftforge.items.wrapper.RecipeWrapper;
public class ProcessingInventory extends RecipeWrapper { public class ProcessingInventory extends RecipeWrapper implements IItemHandler {
protected int remainingTime; protected int remainingTime;
protected int recipeDuration; protected int recipeDuration;
protected boolean appliedRecipe; protected boolean appliedRecipe;
@ -50,8 +51,40 @@ public class ProcessingInventory extends RecipeWrapper {
return inventory; return inventory;
} }
@Override
public int getInventoryStackLimit() {
return 64;
}
public ItemStackHandler getItems() { public ItemStackHandler getItems() {
return (ItemStackHandler) inv; return (ItemStackHandler) inv;
} }
@Override
public int getSlots() {
return 9;
}
@Override
public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) {
if (!isItemValid(slot, stack))
return stack;
return inv.insertItem(slot, stack, simulate);
}
@Override
public ItemStack extractItem(int slot, int amount, boolean simulate) {
return ItemStack.EMPTY;
}
@Override
public int getSlotLimit(int slot) {
return 64;
}
@Override
public boolean isItemValid(int slot, ItemStack stack) {
return slot == 0 && isEmpty();
}
} }

View file

@ -7,10 +7,12 @@ import java.util.List;
import java.util.Random; import java.util.Random;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllRecipes; import com.simibubi.create.AllRecipes;
import com.simibubi.create.AllTileEntities; import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity; import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.logistics.block.IHaveFilter; import com.simibubi.create.modules.logistics.block.IHaveFilter;
import net.minecraft.entity.item.ItemEntity; import net.minecraft.entity.item.ItemEntity;
@ -24,15 +26,23 @@ import net.minecraft.particles.BlockParticleData;
import net.minecraft.particles.IParticleData; import net.minecraft.particles.IParticleData;
import net.minecraft.particles.ItemParticleData; import net.minecraft.particles.ItemParticleData;
import net.minecraft.particles.ParticleTypes; import net.minecraft.particles.ParticleTypes;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
public class SawTileEntity extends KineticTileEntity implements IHaveFilter { public class SawTileEntity extends KineticTileEntity implements IHaveFilter {
public ProcessingInventory inventory; public ProcessingInventory inventory;
private int recipeIndex; private int recipeIndex;
private ItemStack filter; private ItemStack filter;
private LazyOptional<IItemHandler> invProvider = LazyOptional.empty();
public SawTileEntity() { public SawTileEntity() {
super(AllTileEntities.SAW.type); super(AllTileEntities.SAW.type);
@ -40,6 +50,7 @@ public class SawTileEntity extends KineticTileEntity implements IHaveFilter {
inventory.remainingTime = -1; inventory.remainingTime = -1;
filter = ItemStack.EMPTY; filter = ItemStack.EMPTY;
recipeIndex = 0; recipeIndex = 0;
invProvider = LazyOptional.of(() -> inventory);
} }
@Override @Override
@ -78,11 +89,16 @@ public class SawTileEntity extends KineticTileEntity implements IHaveFilter {
return; return;
if (getSpeed() == 0) if (getSpeed() == 0)
return; return;
if (inventory.remainingTime == -1) if (inventory.remainingTime == -1) {
if (!inventory.isEmpty() && !inventory.appliedRecipe)
start();
return; return;
}
float processingSpeed = MathHelper.clamp(Math.abs(getSpeed()) / 32, 1, 128); float processingSpeed = MathHelper.clamp(Math.abs(getSpeed()) / 32, 1, 128);
inventory.remainingTime -= processingSpeed; inventory.remainingTime -= processingSpeed;
if (inventory.remainingTime > 0)
spawnParticles(inventory.getStackInSlot(0)); spawnParticles(inventory.getStackInSlot(0));
if (world.isRemote) if (world.isRemote)
@ -95,10 +111,69 @@ public class SawTileEntity extends KineticTileEntity implements IHaveFilter {
return; return;
} }
Vec3d outPos = VecHelper.getCenterOf(pos).add(getItemMovementVec().scale(.5f).add(0, .5, 0)); Vec3d itemMovement = getItemMovementVec();
Vec3d outMotion = getItemMovementVec().scale(.0625).add(0, .125, 0); Direction itemMovementFacing = Direction.getFacingFromVector(itemMovement.x, itemMovement.y, itemMovement.z);
Vec3d outPos = VecHelper.getCenterOf(pos).add(itemMovement.scale(.5f).add(0, .5, 0));
Vec3d outMotion = itemMovement.scale(.0625).add(0, .125, 0);
if (inventory.remainingTime <= 0) { if (inventory.remainingTime <= 0) {
// Try moving items onto the belt
BlockPos nextPos = pos.add(itemMovement.x, itemMovement.y, itemMovement.z);
if (AllBlocks.BELT.typeOf(world.getBlockState(nextPos))) {
TileEntity te = world.getTileEntity(nextPos);
if (te != null && te instanceof BeltTileEntity) {
for (int slot = 0; slot < inventory.getSizeInventory(); slot++) {
ItemStack stack = inventory.getStackInSlot(slot);
if (stack.isEmpty())
continue;
if (itemMovementFacing.getAxis() == Axis.Z)
itemMovementFacing = itemMovementFacing.getOpposite();
if (((BeltTileEntity) te).tryInsertingFromSide(itemMovementFacing, stack, false))
inventory.setInventorySlotContents(slot, ItemStack.EMPTY);
else {
inventory.remainingTime = 0;
return;
}
}
inventory.clear();
inventory.remainingTime = -1;
sendData();
}
}
// Try moving items onto next saw
if (AllBlocks.SAW.typeOf(world.getBlockState(nextPos))) {
TileEntity te = world.getTileEntity(nextPos);
if (te != null && te instanceof SawTileEntity) {
SawTileEntity sawTileEntity = (SawTileEntity) te;
Vec3d otherMovement = sawTileEntity.getItemMovementVec();
if (Direction.getFacingFromVector(otherMovement.x, otherMovement.y,
otherMovement.z) != itemMovementFacing.getOpposite()) {
for (int slot = 0; slot < inventory.getSizeInventory(); slot++) {
ItemStack stack = inventory.getStackInSlot(slot);
if (stack.isEmpty())
continue;
ProcessingInventory sawInv = sawTileEntity.inventory;
if (sawInv.isEmpty()) {
sawInv.insertItem(0, stack, false);
inventory.setInventorySlotContents(slot, ItemStack.EMPTY);
} else {
inventory.remainingTime = 0;
return;
}
}
inventory.clear();
inventory.remainingTime = -1;
sendData();
}
}
}
// Eject Items
for (int slot = 0; slot < inventory.getSizeInventory(); slot++) { for (int slot = 0; slot < inventory.getSizeInventory(); slot++) {
ItemStack stack = inventory.getStackInSlot(slot); ItemStack stack = inventory.getStackInSlot(slot);
if (stack.isEmpty()) if (stack.isEmpty())
@ -108,6 +183,7 @@ public class SawTileEntity extends KineticTileEntity implements IHaveFilter {
world.addEntity(entityIn); world.addEntity(entityIn);
} }
inventory.clear(); inventory.clear();
world.updateComparatorOutputLevel(pos, getBlockState().getBlock());
inventory.remainingTime = -1; inventory.remainingTime = -1;
sendData(); sendData();
return; return;
@ -116,6 +192,19 @@ public class SawTileEntity extends KineticTileEntity implements IHaveFilter {
return; return;
} }
@Override
public void remove() {
super.remove();
invProvider.invalidate();
}
@Override
public <T> LazyOptional<T> getCapability(Capability<T> cap, Direction side) {
if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
return invProvider.cast();
return super.getCapability(cap, side);
}
protected void spawnParticles(ItemStack stack) { protected void spawnParticles(ItemStack stack) {
if (stack == null || stack.isEmpty()) if (stack == null || stack.isEmpty())
return; return;
@ -198,6 +287,17 @@ public class SawTileEntity extends KineticTileEntity implements IHaveFilter {
inventory.clear(); inventory.clear();
inventory.setInventorySlotContents(0, entity.getItem().copy()); inventory.setInventorySlotContents(0, entity.getItem().copy());
entity.remove();
start();
}
public void start() {
if (!canProcess())
return;
if (inventory.isEmpty())
return;
if (world.isRemote)
return;
List<IRecipe<?>> recipes = getRecipes(); List<IRecipe<?>> recipes = getRecipes();
boolean valid = !recipes.isEmpty(); boolean valid = !recipes.isEmpty();
@ -206,7 +306,6 @@ public class SawTileEntity extends KineticTileEntity implements IHaveFilter {
if (recipes.isEmpty()) { if (recipes.isEmpty()) {
inventory.remainingTime = inventory.recipeDuration = 10; inventory.remainingTime = inventory.recipeDuration = 10;
inventory.appliedRecipe = false; inventory.appliedRecipe = false;
entity.remove();
sendData(); sendData();
return; return;
} }
@ -222,11 +321,9 @@ public class SawTileEntity extends KineticTileEntity implements IHaveFilter {
time = ((CuttingRecipe) recipe).getProcessingDuration(); time = ((CuttingRecipe) recipe).getProcessingDuration();
} }
inventory.remainingTime = time * Math.max(1, (entity.getItem().getCount() / 5)); inventory.remainingTime = time * Math.max(1, (inventory.getStackInSlot(0).getCount() / 5));
inventory.recipeDuration = inventory.remainingTime; inventory.recipeDuration = inventory.remainingTime;
inventory.appliedRecipe = false; inventory.appliedRecipe = false;
entity.remove();
sendData(); sendData();
} }

View file

@ -24,6 +24,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public class SawTileEntityRenderer extends TileEntityRenderer<SawTileEntity> { public class SawTileEntityRenderer extends TileEntityRenderer<SawTileEntity> {
@ -43,9 +44,11 @@ public class SawTileEntityRenderer extends TileEntityRenderer<SawTileEntity> {
boolean alongZ = !te.getBlockState().get(SawBlock.AXIS_ALONG_FIRST_COORDINATE); boolean alongZ = !te.getBlockState().get(SawBlock.AXIS_ALONG_FIRST_COORDINATE);
GlStateManager.pushMatrix(); GlStateManager.pushMatrix();
float offset = te.inventory.recipeDuration != 0 boolean moving = te.inventory.recipeDuration != 0;
? (float) (te.inventory.remainingTime) / te.inventory.recipeDuration float offset = moving ? (float) (te.inventory.remainingTime) / te.inventory.recipeDuration : 0;
: 0; if (moving)
offset = MathHelper.clamp(offset + (-partialTicks + .5f) / te.inventory.recipeDuration, 0, 1);
if (te.getSpeed() == 0) if (te.getSpeed() == 0)
offset = .5f; offset = .5f;
if (te.getSpeed() < 0 ^ alongZ) if (te.getSpeed() < 0 ^ alongZ)

View file

@ -2,7 +2,6 @@ package com.simibubi.create.modules.contraptions.relays.belt;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.function.Consumer; import java.util.function.Consumer;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
@ -14,6 +13,7 @@ import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.INBT; import net.minecraft.nbt.INBT;
import net.minecraft.nbt.ListNBT; import net.minecraft.nbt.ListNBT;
import net.minecraft.nbt.NBTUtil; import net.minecraft.nbt.NBTUtil;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IWorld; import net.minecraft.world.IWorld;
import net.minecraft.world.World; import net.minecraft.world.World;
@ -33,32 +33,52 @@ public enum AllBeltAttachments {
} }
public interface IBeltAttachment { public interface IBeltAttachment {
public List<BlockPos> getPotentialAttachmentLocations(BeltTileEntity te);
public Optional<BlockPos> getValidBeltPositionFor(IWorld world, BlockPos pos, BlockState state); public List<BlockPos> getPotentialAttachmentPositions(IWorld world, BlockPos pos, BlockState beltState);
public boolean handleEntity(BeltTileEntity te, Entity entity, BeltAttachmentState state); public BlockPos getBeltPositionForAttachment(IWorld world, BlockPos pos, BlockState state);
default boolean isAttachedCorrectly(IWorld world, BlockPos attachmentPos, BlockPos beltPos, BlockState attachmentState,
BlockState beltState) {
return true;
}
default boolean processEntity(BeltTileEntity te, Entity entity, BeltAttachmentState state) {
return false;
}
default boolean startProcessingItem(BeltTileEntity te, TransportedItemStack transported, BeltAttachmentState state) {
return false;
}
default boolean processItem(BeltTileEntity te, TransportedItemStack transported, BeltAttachmentState state) {
return false;
}
default void onAttachmentPlaced(IWorld world, BlockPos pos, BlockState state) { default void onAttachmentPlaced(IWorld world, BlockPos pos, BlockState state) {
Optional<BlockPos> beltPos = getValidBeltPositionFor(world, pos, state); BlockPos beltPos = getBeltPositionForAttachment(world, pos, state);
if (!beltPos.isPresent()) TileEntity te = world.getTileEntity(beltPos);
if (te == null || !(te instanceof BeltTileEntity))
return; return;
BeltTileEntity te = (BeltTileEntity) world.getTileEntity(beltPos.get()); BeltTileEntity belt = (BeltTileEntity) te;
if (te == null) if (!isAttachedCorrectly(world, pos, belt.getPos(), state, belt.getBlockState()))
return; return;
te.attachmentTracker.addAttachment(world, pos); belt.attachmentTracker.addAttachment(world, pos);
te.sendData(); belt.markDirty();
belt.sendData();
} }
default void onAttachmentRemoved(IWorld world, BlockPos pos, BlockState state) { default void onAttachmentRemoved(IWorld world, BlockPos pos, BlockState state) {
Optional<BlockPos> beltPos = getValidBeltPositionFor(world, pos, state); BlockPos beltPos = getBeltPositionForAttachment(world, pos, state);
if (!beltPos.isPresent()) TileEntity te = world.getTileEntity(beltPos);
if (te == null || !(te instanceof BeltTileEntity))
return; return;
BeltTileEntity te = (BeltTileEntity) world.getTileEntity(beltPos.get()); BeltTileEntity belt = (BeltTileEntity) te;
if (te == null) if (!isAttachedCorrectly(world, pos, belt.getPos(), state, belt.getBlockState()))
return; return;
te.attachmentTracker.removeAttachment(pos); belt.attachmentTracker.removeAttachment(pos);
te.sendData(); belt.markDirty();
belt.sendData();
} }
} }
@ -67,6 +87,7 @@ public enum AllBeltAttachments {
public BlockPos attachmentPos; public BlockPos attachmentPos;
public int processingDuration; public int processingDuration;
public Entity processingEntity; public Entity processingEntity;
public TransportedItemStack processingStack;
public BeltAttachmentState(IBeltAttachment attachment, BlockPos attachmentPos) { public BeltAttachmentState(IBeltAttachment attachment, BlockPos attachmentPos) {
this.attachment = attachment; this.attachment = attachment;
@ -86,18 +107,24 @@ public enum AllBeltAttachments {
public void findAttachments(BeltTileEntity belt) { public void findAttachments(BeltTileEntity belt) {
for (AllBeltAttachments ba : AllBeltAttachments.values()) { for (AllBeltAttachments ba : AllBeltAttachments.values()) {
List<BlockPos> attachmentPositions = ba.attachment.getPotentialAttachmentLocations(belt);
World world = belt.getWorld(); World world = belt.getWorld();
BlockPos beltPos = belt.getPos();
BlockState beltState = belt.getBlockState();
List<BlockPos> attachmentPositions = ba.attachment.getPotentialAttachmentPositions(world, beltPos,
beltState);
for (BlockPos potentialPos : attachmentPositions) { for (BlockPos potentialPos : attachmentPositions) {
if (!world.isBlockPresent(potentialPos)) if (!world.isBlockPresent(potentialPos))
continue; continue;
BlockState state = world.getBlockState(potentialPos); BlockState state = world.getBlockState(potentialPos);
if (!(state.getBlock() instanceof IBeltAttachment)) if (!(state.getBlock() instanceof IBeltAttachment))
continue; continue;
Optional<BlockPos> validBeltPos = ((IBeltAttachment) state.getBlock()).getValidBeltPositionFor(world, potentialPos, state); IBeltAttachment attachment = (IBeltAttachment) state.getBlock();
if (!validBeltPos.isPresent()) if (!attachment.getBeltPositionForAttachment(world, potentialPos, state).equals(beltPos))
continue; continue;
if (validBeltPos.get().equals(belt.getPos())) if (!attachment.isAttachedCorrectly(world, potentialPos, beltPos, state, beltState))
continue;
addAttachment(world, potentialPos); addAttachment(world, potentialPos);
} }
} }

View file

@ -1,5 +1,6 @@
package com.simibubi.create.modules.contraptions.relays.belt; package com.simibubi.create.modules.contraptions.relays.belt;
import java.util.Collections;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -9,20 +10,28 @@ import com.simibubi.create.foundation.block.IWithTileEntity;
import com.simibubi.create.foundation.block.IWithoutBlockItem; import com.simibubi.create.foundation.block.IWithoutBlockItem;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.modules.contraptions.base.HorizontalKineticBlock; import com.simibubi.create.modules.contraptions.base.HorizontalKineticBlock;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity.TransportedEntityInfo; import com.simibubi.create.modules.contraptions.relays.belt.BeltMovementHandler.TransportedEntityInfo;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.block.material.Material;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.MobEntity;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.DyeColor; import net.minecraft.item.DyeColor;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext;
import net.minecraft.pathfinding.PathNodeType;
import net.minecraft.state.BooleanProperty;
import net.minecraft.state.EnumProperty; import net.minecraft.state.EnumProperty;
import net.minecraft.state.IProperty; import net.minecraft.state.IProperty;
import net.minecraft.state.StateContainer.Builder; import net.minecraft.state.StateContainer.Builder;
import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.BlockRenderLayer;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Direction.AxisDirection; import net.minecraft.util.Direction.AxisDirection;
@ -31,121 +40,110 @@ import net.minecraft.util.IStringSerializable;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult; import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3i;
import net.minecraft.util.math.shapes.IBooleanFunction; import net.minecraft.util.math.shapes.IBooleanFunction;
import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.util.math.shapes.VoxelShapes; import net.minecraft.util.math.shapes.VoxelShapes;
import net.minecraft.world.IBlockReader; import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorldReader;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.common.Tags; import net.minecraftforge.common.Tags;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockItem, IWithTileEntity<BeltTileEntity> { public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockItem, IWithTileEntity<BeltTileEntity> {
public static final IProperty<Slope> SLOPE = EnumProperty.create("slope", Slope.class); public static final IProperty<Slope> SLOPE = EnumProperty.create("slope", Slope.class);
public static final IProperty<Part> PART = EnumProperty.create("part", Part.class); public static final IProperty<Part> PART = EnumProperty.create("part", Part.class);
public static final BooleanProperty CASING = BooleanProperty.create("casing");
private static final VoxelShape FULL = makeCuboidShape(0, 0, 0, 16, 16, 16), private final VoxelShape collisionMask = makeCuboidShape(0, 0, 0, 16, 19, 16);
FLAT_STRAIGHT_X = makeCuboidShape(1, 3, 0, 15, 13, 16),
FLAT_STRAIGHT_Z = makeCuboidShape(0, 3, 1, 16, 13, 15),
VERTICAL_STRAIGHT_X = makeCuboidShape(3, 0, 1, 13, 16, 15),
VERTICAL_STRAIGHT_Z = makeCuboidShape(1, 0, 3, 15, 16, 13),
SLOPE_END_EAST = makeCuboidShape(0, 3, 1, 10, 13, 15),
SLOPE_END_WEST = makeCuboidShape(6, 3, 1, 16, 13, 15),
SLOPE_END_SOUTH = makeCuboidShape(1, 3, 0, 15, 13, 10),
SLOPE_END_NORTH = makeCuboidShape(1, 3, 6, 15, 13, 16),
SLOPE_BUILDING_BLOCK_X = makeCuboidShape(5, 5, 1, 11, 11, 15),
SLOPE_BUILDING_BLOCK_Z = makeCuboidShape(1, 5, 5, 15, 11, 11),
SLOPE_UPWARD_END_EAST = VoxelShapes.or(SLOPE_END_EAST, createHalfSlope(Direction.EAST, false)),
SLOPE_UPWARD_END_WEST = VoxelShapes.or(SLOPE_END_WEST, createHalfSlope(Direction.WEST, false)),
SLOPE_UPWARD_END_SOUTH = VoxelShapes.or(SLOPE_END_SOUTH, createHalfSlope(Direction.SOUTH, false)),
SLOPE_UPWARD_END_NORTH = VoxelShapes.or(SLOPE_END_NORTH, createHalfSlope(Direction.NORTH, false)),
SLOPE_DOWNWARD_END_EAST = VoxelShapes.or(SLOPE_END_EAST, createHalfSlope(Direction.EAST, true)),
SLOPE_DOWNWARD_END_WEST = VoxelShapes.or(SLOPE_END_WEST, createHalfSlope(Direction.WEST, true)),
SLOPE_DOWNWARD_END_SOUTH = VoxelShapes.or(SLOPE_END_SOUTH, createHalfSlope(Direction.SOUTH, true)),
SLOPE_DOWNWARD_END_NORTH = VoxelShapes.or(SLOPE_END_NORTH, createHalfSlope(Direction.NORTH, true)),
SLOPE_EAST = createSlope(Direction.EAST), SLOPE_WEST = createSlope(Direction.WEST),
SLOPE_NORTH = createSlope(Direction.NORTH), SLOPE_SOUTH = createSlope(Direction.SOUTH);
public BeltBlock() { public BeltBlock() {
super(Properties.from(Blocks.BROWN_WOOL)); super(Properties.from(Blocks.BROWN_WOOL));
setDefaultState(getDefaultState().with(SLOPE, Slope.HORIZONTAL).with(PART, Part.START)); setDefaultState(getDefaultState().with(SLOPE, Slope.HORIZONTAL).with(PART, Part.START).with(CASING, false));
}
@Override
public boolean hasShaftTowards(World world, BlockPos pos, BlockState state, Direction face) {
if (face.getAxis() != getRotationAxis(state))
return false;
BeltTileEntity beltEntity = (BeltTileEntity) world.getTileEntity(pos);
return beltEntity != null && beltEntity.hasPulley();
}
@Override
public Axis getRotationAxis(BlockState state) {
return state.get(HORIZONTAL_FACING).rotateY().getAxis();
} }
@Override @Override
public ItemStack getPickBlock(BlockState state, RayTraceResult target, IBlockReader world, BlockPos pos, public ItemStack getPickBlock(BlockState state, RayTraceResult target, IBlockReader world, BlockPos pos,
PlayerEntity player) { PlayerEntity player) {
return new ItemStack(AllItems.BELT_CONNECTOR.item); return AllItems.BELT_CONNECTOR.asStack();
}
@Override
public Material getMaterial(BlockState state) {
return state.get(CASING) ? Material.WOOD : Material.WOOL;
}
@Override
public boolean isFlammable(BlockState state, IBlockReader world, BlockPos pos, Direction face) {
return false;
} }
@Override @Override
public void onLanded(IBlockReader worldIn, Entity entityIn) { public void onLanded(IBlockReader worldIn, Entity entityIn) {
super.onLanded(worldIn, entityIn); super.onLanded(worldIn, entityIn);
if (entityIn instanceof PlayerEntity && entityIn.isSneaking())
return;
if (entityIn instanceof PlayerEntity && ((PlayerEntity) entityIn).moveVertical > 0)
return;
BeltTileEntity belt = null;
BlockPos entityPosition = entityIn.getPosition(); BlockPos entityPosition = entityIn.getPosition();
BlockPos beltPos = null;
if (AllBlocks.BELT.typeOf(worldIn.getBlockState(entityPosition))) if (AllBlocks.BELT.typeOf(worldIn.getBlockState(entityPosition)))
belt = (BeltTileEntity) worldIn.getTileEntity(entityPosition); beltPos = entityPosition;
else if (AllBlocks.BELT.typeOf(worldIn.getBlockState(entityPosition.down()))) else if (AllBlocks.BELT.typeOf(worldIn.getBlockState(entityPosition.down())))
belt = (BeltTileEntity) worldIn.getTileEntity(entityPosition.down()); beltPos = entityPosition.down();
if (beltPos == null)
if (belt == null || !belt.hasSource()) return;
if (!(worldIn instanceof World))
return; return;
BeltTileEntity controller = (BeltTileEntity) worldIn.getTileEntity(belt.getController()); onEntityCollision(worldIn.getBlockState(beltPos), (World) worldIn, beltPos, entityIn);
if (controller == null)
return;
if (controller.passengers == null)
return;
if (controller.passengers.containsKey(entityIn))
controller.passengers.get(entityIn).refresh(belt.getPos(), belt.getBlockState());
else
controller.passengers.put(entityIn, new TransportedEntityInfo(belt.getPos(), belt.getBlockState()));
}
@Override
public float getSlipperiness(BlockState state, IWorldReader world, BlockPos pos, Entity entity) {
return super.getSlipperiness(state, world, pos, entity);
} }
@Override @Override
public void onEntityCollision(BlockState state, World worldIn, BlockPos pos, Entity entityIn) { public void onEntityCollision(BlockState state, World worldIn, BlockPos pos, Entity entityIn) {
if (entityIn instanceof PlayerEntity && entityIn.isSneaking())
return;
if (entityIn instanceof PlayerEntity && ((PlayerEntity) entityIn).moveVertical > 0)
return;
BeltTileEntity belt = null; BeltTileEntity belt = null;
belt = (BeltTileEntity) worldIn.getTileEntity(pos); belt = (BeltTileEntity) worldIn.getTileEntity(pos);
if (belt == null || !belt.hasSource()) if (state.get(SLOPE) == Slope.VERTICAL)
return; return;
if (entityIn instanceof PlayerEntity && entityIn.isSneaking())
return;
if (belt == null || belt.getSpeed() == 0)
return;
if (entityIn instanceof ItemEntity && entityIn.isAlive()) {
if (worldIn.isRemote)
return;
if (entityIn.getMotion().y > 0)
return;
withTileEntityDo(worldIn, pos, te -> {
ItemEntity itemEntity = (ItemEntity) entityIn;
IItemHandler handler = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).orElse(null);
if (handler == null)
return;
ItemStack remainder = handler.insertItem(0, itemEntity.getItem().copy(), false);
if (remainder.isEmpty())
itemEntity.remove();
});
return;
}
BeltTileEntity controller = (BeltTileEntity) worldIn.getTileEntity(belt.getController()); BeltTileEntity controller = (BeltTileEntity) worldIn.getTileEntity(belt.getController());
if (controller == null || controller.passengers == null)
if (controller == null)
return; return;
if (controller.passengers == null)
return;
if (controller.passengers.containsKey(entityIn)) { if (controller.passengers.containsKey(entityIn)) {
TransportedEntityInfo transportedEntityInfo = controller.passengers.get(entityIn); TransportedEntityInfo info = controller.passengers.get(entityIn);
if (transportedEntityInfo.ticksSinceLastCollision != 0 || pos.equals(entityIn.getPosition())) if (info.ticksSinceLastCollision != 0 || pos.equals(entityIn.getPosition()))
transportedEntityInfo.refresh(pos, state); info.refresh(pos, state);
} else } else
controller.passengers.put(entityIn, new TransportedEntityInfo(pos, state)); controller.passengers.put(entityIn, new TransportedEntityInfo(pos, state));
} }
@ -163,19 +161,103 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
if (player.isSneaking() || !player.isAllowEdit()) if (player.isSneaking() || !player.isAllowEdit())
return false; return false;
ItemStack heldItem = player.getHeldItem(handIn); ItemStack heldItem = player.getHeldItem(handIn);
if (!Tags.Items.DYES.contains(heldItem.getItem())) boolean isShaft = heldItem.getItem() == AllBlocks.SHAFT.get().asItem();
return false; boolean isCasing = heldItem.getItem() == AllBlocks.LOGISTICAL_CASING.get().asItem();
boolean isDye = Tags.Items.DYES.contains(heldItem.getItem());
boolean isHand = heldItem.isEmpty() && handIn == Hand.MAIN_HAND;
if (isDye) {
if (worldIn.isRemote) if (worldIn.isRemote)
return true; return true;
withTileEntityDo(worldIn, pos, te -> te.applyColor(DyeColor.getColor(heldItem))); withTileEntityDo(worldIn, pos, te -> {
DyeColor dyeColor = DyeColor.getColor(heldItem);
if (dyeColor == null)
return;
te.applyColor(dyeColor);
});
if (!player.isCreative()) if (!player.isCreative())
heldItem.shrink(1); heldItem.shrink(1);
return true; return true;
} }
TileEntity te = worldIn.getTileEntity(pos);
if (te == null || !(te instanceof BeltTileEntity))
return false;
BeltTileEntity belt = (BeltTileEntity) te;
if (isHand) {
BeltTileEntity controllerBelt = belt.getControllerTE();
if (controllerBelt == null)
return false;
if (worldIn.isRemote)
return true;
controllerBelt.getInventory().forEachWithin(belt.index, .75f, (transportedItemStack) -> {
player.inventory.placeItemBackInInventory(worldIn, transportedItemStack.stack);
return Collections.emptyList();
});
}
if (isShaft) {
if (state.get(PART) != Part.MIDDLE)
return false;
if (worldIn.isRemote)
return true;
if (!player.isCreative())
heldItem.shrink(1);
worldIn.setBlockState(pos, state.with(PART, Part.PULLEY), 2);
belt.attachKinetics();
return true;
}
if (isCasing) {
if (state.get(CASING))
return false;
if (state.get(SLOPE) == Slope.VERTICAL)
return false;
if (!player.isCreative())
heldItem.shrink(1);
worldIn.setBlockState(pos, state.with(CASING, true), 2);
return true;
}
return false;
}
@Override
public ActionResultType onWrenched(BlockState state, ItemUseContext context) {
World world = context.getWorld();
TileEntity te = world.getTileEntity(context.getPos());
if (te == null || !(te instanceof BeltTileEntity))
return ActionResultType.PASS;
BeltTileEntity belt = (BeltTileEntity) te;
PlayerEntity player = context.getPlayer();
if (state.get(CASING)) {
if (world.isRemote)
return ActionResultType.SUCCESS;
world.setBlockState(context.getPos(), state.with(CASING, false), 2);
if (!player.isCreative())
player.inventory.placeItemBackInInventory(world, new ItemStack(AllBlocks.LOGISTICAL_CASING.block));
return ActionResultType.SUCCESS;
}
if (state.get(PART) == Part.PULLEY) {
if (world.isRemote)
return ActionResultType.SUCCESS;
world.setBlockState(context.getPos(), state.with(PART, Part.MIDDLE), 2);
belt.detachKinetics();
belt.attachKinetics();
if (!player.isCreative())
player.inventory.placeItemBackInInventory(world, new ItemStack(AllBlocks.SHAFT.block));
return ActionResultType.SUCCESS;
}
return super.onWrenched(state, context);
}
@Override @Override
protected void fillStateContainer(Builder<Block, BlockState> builder) { protected void fillStateContainer(Builder<Block, BlockState> builder) {
builder.add(SLOPE, PART); builder.add(SLOPE, PART, CASING);
super.fillStateContainer(builder); super.fillStateContainer(builder);
} }
@ -185,46 +267,30 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
} }
@Override @Override
public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { public PathNodeType getAiPathNodeType(BlockState state, IBlockReader world, BlockPos pos, MobEntity entity) {
Direction facing = state.get(HORIZONTAL_FACING); return PathNodeType.DANGER_OTHER;
Axis axis = facing.getAxis();
Part part = state.get(PART);
Slope slope = state.get(SLOPE);
if (slope == Slope.HORIZONTAL)
return axis == Axis.Z ? FLAT_STRAIGHT_X : FLAT_STRAIGHT_Z;
if (slope == Slope.VERTICAL)
return axis == Axis.X ? VERTICAL_STRAIGHT_X : VERTICAL_STRAIGHT_Z;
if (part != Part.MIDDLE) {
if (part == Part.START)
slope = slope == Slope.UPWARD ? Slope.DOWNWARD : Slope.UPWARD;
else
facing = facing.getOpposite();
if (facing == Direction.NORTH)
return slope == Slope.UPWARD ? SLOPE_UPWARD_END_NORTH : SLOPE_DOWNWARD_END_NORTH;
if (facing == Direction.SOUTH)
return slope == Slope.UPWARD ? SLOPE_UPWARD_END_SOUTH : SLOPE_DOWNWARD_END_SOUTH;
if (facing == Direction.EAST)
return slope == Slope.UPWARD ? SLOPE_UPWARD_END_EAST : SLOPE_DOWNWARD_END_EAST;
if (facing == Direction.WEST)
return slope == Slope.UPWARD ? SLOPE_UPWARD_END_WEST : SLOPE_DOWNWARD_END_WEST;
} }
if (slope == Slope.DOWNWARD) @Override
facing = facing.getOpposite(); public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
return VoxelShapes.or(BeltShapes.getShape(state), BeltShapes.getCasingShape(state));
}
if (facing == Direction.NORTH) @Override
return SLOPE_NORTH; public VoxelShape getCollisionShape(BlockState state, IBlockReader worldIn, BlockPos pos,
if (facing == Direction.SOUTH) ISelectionContext context) {
return SLOPE_SOUTH; VoxelShape shape = getShape(state, worldIn, pos, context);
if (facing == Direction.EAST) BeltTileEntity belt = (BeltTileEntity) worldIn.getTileEntity(pos);
return SLOPE_EAST; if (belt == null || context.getEntity() == null)
if (facing == Direction.WEST) return shape;
return SLOPE_WEST; BeltTileEntity controller = (BeltTileEntity) worldIn.getTileEntity(belt.getController());
if (controller == null)
return shape;
if (controller.passengers == null || !controller.passengers.containsKey(context.getEntity())) {
return VoxelShapes.combine(collisionMask, shape, IBooleanFunction.AND);
}
return FULL; return shape;
} }
@Override @Override
@ -233,15 +299,22 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
} }
@Override @Override
protected boolean hasStaticPart() { public boolean canRenderInLayer(BlockState state, BlockRenderLayer layer) {
return false; return state.get(CASING) && layer == getRenderLayer();
} }
@Override @Override
public void onBlockHarvested(World worldIn, BlockPos pos, BlockState state, PlayerEntity player) { public void onBlockHarvested(World worldIn, BlockPos pos, BlockState state, PlayerEntity player) {
withTileEntityDo(worldIn, pos, te -> { withTileEntityDo(worldIn, pos, te -> {
if (te.hasPulley()) if (worldIn.isRemote)
return;
if (te.hasPulley() && (player == null || !player.isCreative()))
Block.spawnDrops(AllBlocks.SHAFT.get().getDefaultState(), worldIn, pos); Block.spawnDrops(AllBlocks.SHAFT.get().getDefaultState(), worldIn, pos);
if (te.isController()) {
BeltInventory inv = te.getInventory();
for (TransportedItemStack stack : inv.items)
inv.eject(stack);
}
}); });
super.onBlockHarvested(worldIn, pos, state, player); super.onBlockHarvested(worldIn, pos, state, player);
} }
@ -250,6 +323,8 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) { public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) {
if (worldIn.isRemote) if (worldIn.isRemote)
return; return;
if (state.getBlock() == newState.getBlock())
return;
boolean endWasDestroyed = state.get(PART) == Part.END; boolean endWasDestroyed = state.get(PART) == Part.END;
TileEntity tileEntity = worldIn.getTileEntity(pos); TileEntity tileEntity = worldIn.getTileEntity(pos);
@ -274,16 +349,20 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
break; break;
BeltTileEntity te = (BeltTileEntity) worldIn.getTileEntity(toDestroy); BeltTileEntity te = (BeltTileEntity) worldIn.getTileEntity(toDestroy);
boolean hasPulley = te.hasPulley(); if (te.isController()) {
BeltInventory inv = te.getInventory();
for (TransportedItemStack stack : inv.items)
inv.eject(stack);
}
te.setSource(null); te.setSource(null);
te.remove(); te.remove();
if (hasPulley) { if (te.hasPulley())
worldIn.setBlockState(toDestroy, AllBlocks.SHAFT.get().getDefaultState() worldIn.setBlockState(toDestroy, AllBlocks.SHAFT.get().getDefaultState()
.with(BlockStateProperties.AXIS, getRotationAxis(destroyedBlock)), 3); .with(BlockStateProperties.AXIS, getRotationAxis(destroyedBlock)), 3);
} else { else
worldIn.destroyBlock(toDestroy, false); worldIn.destroyBlock(toDestroy, false);
}
if (destroyedBlock.get(PART) == Part.END) if (destroyedBlock.get(PART) == Part.END)
break; break;
@ -308,19 +387,6 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
} }
@Override
public boolean hasShaftTowards(World world, BlockPos pos, BlockState state, Direction face) {
if (face.getAxis() != getRotationAxis(state))
return false;
BeltTileEntity beltEntity = (BeltTileEntity) world.getTileEntity(pos);
return beltEntity != null && beltEntity.hasPulley();
}
@Override
public Axis getRotationAxis(BlockState state) {
return state.get(HORIZONTAL_FACING).getAxis() == Axis.X ? Axis.Z : Axis.X;
}
public enum Slope implements IStringSerializable { public enum Slope implements IStringSerializable {
HORIZONTAL, UPWARD, DOWNWARD, VERTICAL; HORIZONTAL, UPWARD, DOWNWARD, VERTICAL;
@ -331,7 +397,7 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
} }
public enum Part implements IStringSerializable { public enum Part implements IStringSerializable {
START, MIDDLE, END; START, MIDDLE, END, PULLEY;
@Override @Override
public String getName() { public String getName() {
@ -339,18 +405,6 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
} }
} }
public static boolean isUpperEnd(BlockState state, float speed) {
Direction facing = state.get(HORIZONTAL_FACING);
if (state.get(SLOPE) == Slope.UPWARD && state.get(PART) == Part.END) {
return facing.getAxisDirection().getOffset() * Math.signum(speed) == (facing.getAxis() == Axis.X ? -1 : 1);
}
if (state.get(SLOPE) == Slope.DOWNWARD && state.get(PART) == Part.START) {
return facing.getAxisDirection().getOffset() * Math.signum(speed) == (facing.getAxis() == Axis.Z ? -1 : 1);
}
return false;
}
public static List<BlockPos> getBeltChain(World world, BlockPos controllerPos) { public static List<BlockPos> getBeltChain(World world, BlockPos controllerPos) {
List<BlockPos> positions = new LinkedList<>(); List<BlockPos> positions = new LinkedList<>();
@ -382,33 +436,34 @@ public class BeltBlock extends HorizontalKineticBlock implements IWithoutBlockIt
return positions; return positions;
} }
protected static VoxelShape createSlope(Direction facing) { @Override
return VoxelShapes.or(createHalfSlope(facing.getOpposite(), false), createHalfSlope(facing, true)); protected boolean hasStaticPart() {
return false;
} }
protected static VoxelShape createHalfSlope(Direction facing, boolean upward) { public static boolean canAccessFromSide(Direction facing, BlockState belt) {
VoxelShape shape = VoxelShapes.empty(); if (facing == null)
VoxelShape buildingBlock = facing.getAxis() == Axis.X ? SLOPE_BUILDING_BLOCK_X : SLOPE_BUILDING_BLOCK_Z; return true;
Vec3i directionVec = facing.getDirectionVec(); if (!belt.get(BeltBlock.CASING))
return false;
Part part = belt.get(BeltBlock.PART);
if (part != Part.MIDDLE && facing.getAxis() == belt.get(HORIZONTAL_FACING).rotateY().getAxis())
return false;
int x = directionVec.getX(); Slope slope = belt.get(BeltBlock.SLOPE);
int y = upward ? 1 : -1; if (slope != Slope.HORIZONTAL) {
int z = directionVec.getZ(); if (slope == Slope.DOWNWARD && part == Part.END)
return true;
if (slope == Slope.UPWARD && part == Part.START)
return true;
Direction beltSide = belt.get(HORIZONTAL_FACING);
if (slope == Slope.DOWNWARD)
beltSide = beltSide.getOpposite();
if (beltSide == facing)
return false;
}
for (int segment = 0; segment < 6; segment++) return true;
shape = VoxelShapes.or(shape,
buildingBlock.withOffset(x * segment / 16f, y * segment / 16f, z * segment / 16f));
if (!upward)
return shape;
VoxelShape mask = makeCuboidShape(0, -8, 0, 16, 24, 16);
for (int segment = 6; segment < 11; segment++)
shape = VoxelShapes.or(shape,
VoxelShapes.combine(mask,
buildingBlock.withOffset(x * segment / 16f, y * segment / 16f, z * segment / 16f),
IBooleanFunction.AND));
return shape;
} }
} }

View file

@ -6,6 +6,7 @@ import java.util.List;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.CreateConfig; import com.simibubi.create.CreateConfig;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity; import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.relays.ShaftBlock;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
@ -22,9 +23,9 @@ import net.minecraft.util.Direction.AxisDirection;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
public class BeltItem extends Item { public class BeltConnectorItem extends Item {
public BeltItem(Properties properties) { public BeltConnectorItem(Properties properties) {
super(properties); super(properties);
} }
@ -95,11 +96,23 @@ public class BeltItem extends Item {
List<BlockPos> beltsToCreate = getBeltChainBetween(start, end, slope, facing); List<BlockPos> beltsToCreate = getBeltChainBetween(start, end, slope, facing);
BlockState beltBlock = AllBlocks.BELT.get().getDefaultState(); BlockState beltBlock = AllBlocks.BELT.get().getDefaultState();
int index = 0;
for (BlockPos pos : beltsToCreate) { for (BlockPos pos : beltsToCreate) {
BeltBlock.Part part = pos.equals(start) ? Part.START : pos.equals(end) ? Part.END : Part.MIDDLE; BeltBlock.Part part = pos.equals(start) ? Part.START : pos.equals(end) ? Part.END : Part.MIDDLE;
boolean pulley = AllBlocks.SHAFT.typeOf(world.getBlockState(pos));
if (part == Part.MIDDLE && pulley)
part = Part.PULLEY;
world.setBlockState(pos, beltBlock.with(BeltBlock.SLOPE, slope).with(BeltBlock.PART, part) world.setBlockState(pos, beltBlock.with(BeltBlock.SLOPE, slope).with(BeltBlock.PART, part)
.with(BeltBlock.HORIZONTAL_FACING, facing), 3); .with(BeltBlock.HORIZONTAL_FACING, facing), 3);
connectBelt(world, pos, start);
BeltTileEntity te = (BeltTileEntity) world.getTileEntity(pos);
if (te != null) {
te.setController(start);
te.beltLength = beltsToCreate.size();
te.index = index;
}
index++;
} }
} }
@ -151,12 +164,6 @@ public class BeltItem extends Item {
return positions; return positions;
} }
private void connectBelt(World world, BlockPos pos, BlockPos target) {
BeltTileEntity te = (BeltTileEntity) world.getTileEntity(pos);
if (te != null)
te.setController(target);
}
public static boolean canConnect(World world, BlockPos first, BlockPos second) { public static boolean canConnect(World world, BlockPos first, BlockPos second) {
if (!world.isAreaLoaded(first, 1)) if (!world.isAreaLoaded(first, 1))
return false; return false;
@ -190,11 +197,15 @@ public class BeltItem extends Item {
int limit = 1000; int limit = 1000;
for (BlockPos currentPos = first.add(step); !currentPos.equals(second) for (BlockPos currentPos = first.add(step); !currentPos.equals(second)
&& limit-- > 0; currentPos = currentPos.add(step)) { && limit-- > 0; currentPos = currentPos.add(step)) {
if (!world.getBlockState(currentPos).getMaterial().isReplaceable()) BlockState blockState = world.getBlockState(currentPos);
if (AllBlocks.SHAFT.typeOf(blockState) && blockState.get(ShaftBlock.AXIS) == axis)
continue;
if (!blockState.getMaterial().isReplaceable())
return false; return false;
} }
return true; return true;
} }
public static boolean validateAxis(World world, BlockPos pos) { public static boolean validateAxis(World world, BlockPos pos) {

View file

@ -23,7 +23,7 @@ import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World; import net.minecraft.world.World;
public class BeltItemHandler { public class BeltConnectorItemHandler {
private static Random r = new Random(); private static Random r = new Random();
@ -73,7 +73,7 @@ public class BeltItemHandler {
if (!selected.withinDistance(first, CreateConfig.parameters.maxBeltLength.get())) if (!selected.withinDistance(first, CreateConfig.parameters.maxBeltLength.get()))
return; return;
boolean canConnect = BeltItem.validateAxis(world, selected) && BeltItem.canConnect(world, first, selected); boolean canConnect = BeltConnectorItem.validateAxis(world, selected) && BeltConnectorItem.canConnect(world, first, selected);
Vec3d start = new Vec3d(first); Vec3d start = new Vec3d(first);
Vec3d end = new Vec3d(selected); Vec3d end = new Vec3d(selected);

View file

@ -0,0 +1,380 @@
package com.simibubi.create.modules.contraptions.relays.belt;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Function;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.BeltAttachmentState;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.Vec3i;
import net.minecraft.world.World;
import net.minecraftforge.common.util.Constants.NBT;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper;
public class BeltInventory {
final BeltTileEntity belt;
final List<TransportedItemStack> items;
boolean beltMovementPositive;
final float SEGMENT_WINDOW = .75f;
public BeltInventory(BeltTileEntity te) {
this.belt = te;
items = new LinkedList<>();
}
public void tick() {
// Reverse item collection if belt just reversed
if (beltMovementPositive != movingPositive()) {
beltMovementPositive = movingPositive();
Collections.reverse(items);
belt.markDirty();
belt.sendData();
}
// Assuming the first entry is furthest on the belt
TransportedItemStack stackInFront = null;
TransportedItemStack current = null;
Iterator<TransportedItemStack> iterator = items.iterator();
float beltSpeed = belt.getDirectionAwareBeltMovementSpeed();
float spacing = 1;
Items: while (iterator.hasNext()) {
stackInFront = current;
current = iterator.next();
current.prevBeltPosition = current.beltPosition;
current.prevSideOffset = current.sideOffset;
if (current.stack.isEmpty()) {
iterator.remove();
current = null;
continue;
}
float movement = beltSpeed;
// Don't move if locked
boolean onClient = belt.getWorld().isRemote;
if (onClient && current.locked)
continue;
// Don't move if other items are waiting in front
float currentPos = current.beltPosition;
if (stackInFront != null) {
float diff = stackInFront.beltPosition - currentPos;
if (Math.abs(diff) <= spacing)
continue;
movement = beltMovementPositive ? Math.min(movement, diff - spacing)
: Math.max(movement, diff + spacing);
}
// Determine current segment
int segmentBefore = (int) currentPos;
float min = segmentBefore + .5f - (SEGMENT_WINDOW / 2);
float max = segmentBefore + .5f + (SEGMENT_WINDOW / 2);
if (currentPos < min || currentPos > max)
segmentBefore = -1;
// Don't move beyond the edge
float diffToEnd = beltMovementPositive ? belt.beltLength - currentPos : -currentPos;
float limitedMovement = beltMovementPositive ? Math.min(movement, diffToEnd)
: Math.max(movement, diffToEnd);
if (!onClient) {
// Don't move if belt attachments want to continue processing
if (segmentBefore != -1 && current.locked) {
BeltTileEntity beltSegment = getBeltSegment(segmentBefore);
if (beltSegment != null) {
current.locked = false;
for (BeltAttachmentState attachmentState : beltSegment.attachmentTracker.attachments) {
if (attachmentState.attachment.processItem(beltSegment, current, attachmentState))
current.locked = true;
}
if (!current.locked || current.stack.isEmpty())
belt.sendData();
continue;
}
}
// See if any new belt processing catches the item
int upcomingSegment = (int) (current.beltPosition + (beltMovementPositive ? .5f : -.5f));
for (int segment = upcomingSegment; beltMovementPositive
? segment + .5f <= current.beltPosition + limitedMovement
: segment + .5f >= current.beltPosition + limitedMovement; segment += beltMovementPositive ? 1
: -1) {
BeltTileEntity beltSegment = getBeltSegment(segmentBefore);
if (beltSegment == null)
break;
for (BeltAttachmentState attachmentState : beltSegment.attachmentTracker.attachments) {
if (attachmentState.attachment.startProcessingItem(beltSegment, current, attachmentState)) {
current.beltPosition = segment + .5f + (beltMovementPositive ? 1 / 64f : -1 / 64f);
current.locked = true;
belt.sendData();
continue Items;
}
}
}
}
// Apply Movement
current.beltPosition += limitedMovement;
current.sideOffset += (current.getTargetSideOffset() - current.sideOffset) * Math.abs(limitedMovement) * 2f;
currentPos = current.beltPosition;
// Determine segment after movement
int segmentAfter = (int) currentPos;
min = segmentAfter + .5f - (SEGMENT_WINDOW / 2);
max = segmentAfter + .5f + (SEGMENT_WINDOW / 2);
if (currentPos < min || currentPos > max)
segmentAfter = -1;
// Item changed segments
World world = belt.getWorld();
if (segmentBefore != segmentAfter) {
for (int segment : new int[] { segmentBefore, segmentAfter }) {
if (segment == -1)
continue;
if (!world.isRemote)
world.updateComparatorOutputLevel(getPositionForOffset(segment),
belt.getBlockState().getBlock());
}
}
// End reached
if (limitedMovement != movement) {
if (world.isRemote)
continue;
BlockPos nextPosition = getPositionForOffset(beltMovementPositive ? belt.beltLength : -1);
BlockState state = world.getBlockState(nextPosition);
Direction movementFacing = belt.getMovementFacing();
// next block is a basin or a saw
if (AllBlocks.BASIN.typeOf(state) || AllBlocks.SAW.typeOf(state)) {
TileEntity te = world.getTileEntity(nextPosition);
if (te != null) {
LazyOptional<IItemHandler> optional = te
.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, Direction.UP);
if (optional.isPresent()) {
IItemHandler itemHandler = optional.orElse(null);
ItemStack remainder = ItemHandlerHelper.insertItemStacked(itemHandler, current.stack.copy(),
false);
if (remainder.equals(current.stack, false))
continue;
current.stack = remainder;
if (remainder.isEmpty()) {
iterator.remove();
current = null;
}
belt.sendData();
}
}
continue;
}
// next block is not a belt
if (!AllBlocks.BELT.typeOf(state)) {
if (!Block.hasSolidSide(state, world, nextPosition, movementFacing.getOpposite())) {
eject(current);
iterator.remove();
current = null;
belt.sendData();
}
continue;
}
// Next block is a belt
TileEntity te = world.getTileEntity(nextPosition);
if (te == null || !(te instanceof BeltTileEntity))
continue;
BeltTileEntity nextBelt = (BeltTileEntity) te;
Direction nextMovementFacing = nextBelt.getMovementFacing();
// next belt goes the opposite way
if (nextMovementFacing == movementFacing.getOpposite())
continue;
// Inserting into other belt
if (nextBelt.tryInsertingFromSide(movementFacing, current, false)) {
iterator.remove();
current = null;
belt.sendData();
}
}
}
}
public boolean canInsertAt(int segment) {
return canInsertFrom(segment, Direction.UP);
}
public boolean canInsertFrom(int segment, Direction side) {
float min = segment + .5f - (SEGMENT_WINDOW / 2);
float max = segment + .5f + (SEGMENT_WINDOW / 2);
for (TransportedItemStack stack : items) {
float currentPos = stack.beltPosition;
// Searched past relevant stacks
if (beltMovementPositive ? currentPos < segment : currentPos - 1 > segment)
break;
// Item inside extraction window
if (currentPos > min && currentPos < max)
return false;
// Items on the belt get prioritized if the previous item was inserted on the
// same segment
if (stack.insertedAt == segment && stack.insertedFrom == side
&& (beltMovementPositive ? currentPos <= segment + 1.5 : currentPos - 1.5 >= segment))
return false;
}
return true;
}
protected void insert(TransportedItemStack newStack) {
if (items.isEmpty())
items.add(newStack);
else {
int index = 0;
for (TransportedItemStack stack : items) {
if (stack.compareTo(newStack) > 0 == beltMovementPositive)
break;
index++;
}
items.add(index, newStack);
}
}
public TransportedItemStack getStackAtOffset(int offset) {
float min = offset + .5f - (SEGMENT_WINDOW / 2);
float max = offset + .5f + (SEGMENT_WINDOW / 2);
for (TransportedItemStack stack : items) {
if (stack.beltPosition > max)
break;
if (stack.beltPosition > min)
return stack;
}
return null;
}
public void read(CompoundNBT nbt) {
items.clear();
nbt.getList("Items", NBT.TAG_COMPOUND)
.forEach(inbt -> items.add(TransportedItemStack.read((CompoundNBT) inbt)));
beltMovementPositive = nbt.getBoolean("PositiveOrder");
}
public CompoundNBT write() {
CompoundNBT nbt = new CompoundNBT();
ListNBT itemsNBT = new ListNBT();
items.forEach(stack -> itemsNBT.add(stack.serializeNBT()));
nbt.put("Items", itemsNBT);
nbt.putBoolean("PositiveOrder", beltMovementPositive);
return nbt;
}
public void eject(TransportedItemStack stack) {
ItemStack ejected = stack.stack;
Vec3d outPos = getVectorForOffset(stack.beltPosition);
float movementSpeed = Math.max(Math.abs(belt.getBeltMovementSpeed()), 1 / 8f);
Vec3d outMotion = new Vec3d(belt.getBeltChainDirection()).scale(movementSpeed).add(0, 1 / 8f, 0);
outPos.add(outMotion.normalize());
ItemEntity entity = new ItemEntity(belt.getWorld(), outPos.x, outPos.y + 6 / 16f, outPos.z, ejected);
entity.setMotion(outMotion);
entity.velocityChanged = true;
belt.getWorld().addEntity(entity);
}
public Vec3d getVectorForOffset(float offset) {
Slope slope = belt.getBlockState().get(BeltBlock.SLOPE);
int verticality = slope == Slope.DOWNWARD ? -1 : slope == Slope.UPWARD ? 1 : 0;
float verticalMovement = verticality;
if (offset < .5)
verticalMovement = 0;
verticalMovement = verticalMovement * (Math.min(offset, belt.beltLength - .5f) - .5f);
Vec3d vec = VecHelper.getCenterOf(belt.getPos());
vec = vec.add(new Vec3d(belt.getBeltFacing().getDirectionVec()).scale(offset - .5f)).add(0, verticalMovement,
0);
return vec;
}
private BeltTileEntity getBeltSegment(int segment) {
BlockPos pos = getPositionForOffset(segment);
TileEntity te = belt.getWorld().getTileEntity(pos);
if (te == null || !(te instanceof BeltTileEntity))
return null;
return (BeltTileEntity) te;
}
private BlockPos getPositionForOffset(int offset) {
BlockPos pos = belt.getPos();
Vec3i vec = belt.getBeltFacing().getDirectionVec();
Slope slope = belt.getBlockState().get(BeltBlock.SLOPE);
int verticality = slope == Slope.DOWNWARD ? -1 : slope == Slope.UPWARD ? 1 : 0;
return pos.add(offset * vec.getX(), MathHelper.clamp(offset, 0, belt.beltLength - 1) * verticality,
offset * vec.getZ());
}
private boolean movingPositive() {
return belt.getDirectionAwareBeltMovementSpeed() > 0;
}
public IItemHandler createHandlerForSegment(int segment) {
return new ItemHandlerBeltSegment(this, segment);
}
public void forEachWithin(float position, float distance,
Function<TransportedItemStack, List<TransportedItemStack>> callback) {
List<TransportedItemStack> toBeAdded = new ArrayList<>();
boolean dirty = false;
for (Iterator<TransportedItemStack> iterator = items.iterator(); iterator.hasNext();) {
TransportedItemStack transportedItemStack = iterator.next();
if (Math.abs(position - transportedItemStack.beltPosition) < distance) {
List<TransportedItemStack> apply = callback.apply(transportedItemStack);
if (apply == null)
continue;
dirty = true;
toBeAdded.addAll(apply);
iterator.remove();
}
}
toBeAdded.forEach(this::insert);
if (dirty) {
belt.markDirty();
belt.sendData();
}
}
}

View file

@ -0,0 +1,86 @@
package com.simibubi.create.modules.contraptions.relays.belt;
import java.nio.ByteBuffer;
import com.simibubi.create.Create;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.BufferManipulator;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.texture.AtlasTexture;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.Direction;
import net.minecraft.util.ResourceLocation;
public class BeltModelAnimator extends BufferManipulator {
protected static TextureAtlasSprite beltTextures;
protected static TextureAtlasSprite originalTexture;
public BeltModelAnimator(ByteBuffer template) {
super(template);
}
private void initSprites() {
AtlasTexture textureMap = Minecraft.getInstance().getTextureMap();
originalTexture = textureMap.getSprite(new ResourceLocation(Create.ID, "block/belt"));
beltTextures = textureMap.getSprite(new ResourceLocation(Create.ID, "block/belt_animated"));
}
public ByteBuffer getTransformed(BeltTileEntity te, float x, float y, float z, int color) {
original.rewind();
mutable.rewind();
float textureOffsetX = 0;
float textureOffsetY = 0;
if (te.getSpeed() != 0) {
float time = AnimationTickHolder.getRenderTick();
Direction direction = te.getBlockState().get(BlockStateProperties.HORIZONTAL_FACING);
if (direction == Direction.EAST || direction == Direction.NORTH)
time = -time;
int textureIndex = (int) ((te.getSpeed() * time / 8) % 16);
if (textureIndex < 0)
textureIndex += 16;
if (beltTextures == null)
initSprites();
textureOffsetX = beltTextures.getInterpolatedU((textureIndex % 4) * 4) - originalTexture.getMinU();
textureOffsetY = beltTextures.getInterpolatedV((textureIndex / 4) * 4) - originalTexture.getMinV();
}
final BlockState blockState = te.getBlockState();
int packedLightCoords = blockState.getPackedLightmapCoords(te.getWorld(), te.getPos());
float texOffX = textureOffsetX;
float texOffY = textureOffsetY;
boolean defaultColor = color == -1;
int b = defaultColor ? 128 : color & 0xFF;
int g = defaultColor ? 128 : (color >> 8) & 0xFF;
int r = defaultColor ? 128 : (color >> 16) & 0xFF;
for (int vertex = 0; vertex < vertexCount(original); vertex++) {
putPos(mutable, vertex, getX(original, vertex) + x, getY(original, vertex) + y, getZ(original, vertex) + z);
putLight(mutable, vertex, packedLightCoords);
int bufferPosition = getBufferPosition(vertex);
mutable.putFloat(bufferPosition + 16, original.getFloat(bufferPosition + 16) + texOffX);
mutable.putFloat(bufferPosition + 20, original.getFloat(bufferPosition + 20) + texOffY);
byte lumByte = getR(original, vertex);
float lum = (lumByte < 0 ? 255 + lumByte : lumByte) / 256f;
int r2 = (int) (r * lum);
int g2 = (int) (g * lum);
int b2 = (int) (b * lum);
putColor(mutable, vertex, (byte) r2, (byte) g2, (byte) b2, (byte) 255);
}
return mutable;
}
public static void invalidateCache() {
beltTextures = null;
}
}

View file

@ -0,0 +1,184 @@
package com.simibubi.create.modules.contraptions.relays.belt;
import static net.minecraft.entity.MoverType.SELF;
import static net.minecraft.util.Direction.AxisDirection.NEGATIVE;
import static net.minecraft.util.Direction.AxisDirection.POSITIVE;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.BeltAttachmentState;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.Effects;
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.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.Vec3i;
import net.minecraft.world.World;
public class BeltMovementHandler {
public static class TransportedEntityInfo {
int ticksSinceLastCollision;
BlockPos lastCollidedPos;
BlockState lastCollidedState;
public TransportedEntityInfo(BlockPos collision, BlockState belt) {
refresh(collision, belt);
}
public void refresh(BlockPos collision, BlockState belt) {
ticksSinceLastCollision = 0;
lastCollidedPos = new BlockPos(collision).toImmutable();
lastCollidedState = belt;
}
public TransportedEntityInfo tick() {
ticksSinceLastCollision++;
return this;
}
}
public static boolean canBeTransported(Entity entity) {
if (!entity.isAlive())
return false;
if (entity instanceof PlayerEntity && ((PlayerEntity) entity).isSneaking())
return false;
return true;
}
public static void transportEntity(BeltTileEntity beltTe, Entity entityIn, TransportedEntityInfo info) {
BlockPos pos = info.lastCollidedPos;
World world = beltTe.getWorld();
TileEntity te = world.getTileEntity(pos);
TileEntity tileEntityBelowPassenger = world.getTileEntity(entityIn.getPosition());
BlockState blockState = info.lastCollidedState;
Direction movementFacing = Direction.getFacingFromAxisDirection(
blockState.get(BlockStateProperties.HORIZONTAL_FACING).getAxis(),
beltTe.getSpeed() < 0 ? POSITIVE : NEGATIVE);
boolean collidedWithBelt = te instanceof BeltTileEntity;
boolean betweenBelts = tileEntityBelowPassenger instanceof BeltTileEntity && tileEntityBelowPassenger != te;
// Don't fight other Belts
if (!collidedWithBelt || betweenBelts) {
return;
}
// Too slow
boolean notHorizontal = beltTe.getBlockState().get(BeltBlock.SLOPE) != Slope.HORIZONTAL;
if (Math.abs(beltTe.getSpeed()) < (notHorizontal ? 32 : 1))
return;
// Not on top
if (entityIn.posY - .25f < pos.getY())
return;
// Lock entities in place
boolean isPlayer = entityIn instanceof PlayerEntity;
if (entityIn instanceof LivingEntity && !isPlayer) {
((LivingEntity) entityIn).addPotionEffect(new EffectInstance(Effects.SLOWNESS, 10, 1, false, false));
}
BeltTileEntity belt = (BeltTileEntity) te;
// Attachment pauses movement
for (BeltAttachmentState state : belt.attachmentTracker.attachments) {
if (state.attachment.processEntity(belt, entityIn, state)) {
info.ticksSinceLastCollision--;
return;
}
}
final Direction beltFacing = blockState.get(BlockStateProperties.HORIZONTAL_FACING);
final Slope slope = blockState.get(BeltBlock.SLOPE);
final Axis axis = beltFacing.getAxis();
float movementSpeed = beltTe.getBeltMovementSpeed();
final Direction movementDirection = Direction.getFacingFromAxis(axis == Axis.X ? NEGATIVE : POSITIVE, axis);
Vec3i centeringDirection = Direction.getFacingFromAxis(POSITIVE, beltFacing.rotateY().getAxis())
.getDirectionVec();
Vec3d movement = new Vec3d(movementDirection.getDirectionVec()).scale(movementSpeed);
double diffCenter = axis == Axis.Z ? (pos.getX() + .5f - entityIn.posX) : (pos.getZ() + .5f - entityIn.posZ);
if (Math.abs(diffCenter) > 48 / 64f)
return;
Part part = blockState.get(BeltBlock.PART);
float top = 13 / 16f;
boolean onSlope = notHorizontal && (part == Part.MIDDLE || part == Part.PULLEY
|| part == (slope == Slope.UPWARD ? Part.END : Part.START) && entityIn.posY - pos.getY() < top
|| part == (slope == Slope.UPWARD ? Part.START : Part.END) && entityIn.posY - pos.getY() > top);
boolean movingDown = onSlope && slope == (movementFacing == beltFacing ? Slope.DOWNWARD : Slope.UPWARD);
boolean movingUp = onSlope && slope == (movementFacing == beltFacing ? Slope.UPWARD : Slope.DOWNWARD);
if (beltFacing.getAxis() == Axis.Z) {
boolean b = movingDown;
movingDown = movingUp;
movingUp = b;
}
if (movingUp)
movement = movement.add(0, Math.abs(axis.getCoordinate(movement.x, movement.y, movement.z)), 0);
if (movingDown)
movement = movement.add(0, -Math.abs(axis.getCoordinate(movement.x, movement.y, movement.z)), 0);
Vec3d centering = new Vec3d(centeringDirection).scale(diffCenter * Math.min(Math.abs(movementSpeed), .1f) * 4);
movement = movement.add(centering);
float step = entityIn.stepHeight;
if (!isPlayer)
entityIn.stepHeight = 1;
// Entity Collisions
if (Math.abs(movementSpeed) < .5f) {
Vec3d checkDistance = movement.normalize().scale(0.5);
AxisAlignedBB bb = entityIn.getBoundingBox();
AxisAlignedBB checkBB = new AxisAlignedBB(bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ);
if (!world
.getEntitiesWithinAABBExcludingEntity(entityIn, checkBB.offset(checkDistance)
.grow(-Math.abs(checkDistance.x), -Math.abs(checkDistance.y), -Math.abs(checkDistance.z)))
.isEmpty()) {
entityIn.setMotion(0, 0, 0);
info.ticksSinceLastCollision--;
return;
}
}
if (movingUp) {
float minVelocity = .13f;
float yMovement = (float) -(Math.max(Math.abs(movement.y), minVelocity));
entityIn.move(SELF, new Vec3d(0, yMovement, 0));
entityIn.move(SELF, movement.mul(1, 0, 1));
} else if (movingDown) {
entityIn.move(SELF, movement.mul(1, 0, 1));
entityIn.move(SELF, movement.mul(0, 1, 0));
} else {
entityIn.move(SELF, movement);
}
if (!isPlayer)
entityIn.stepHeight = step;
boolean movedPastEndingSlope = onSlope && (AllBlocks.BELT.typeOf(world.getBlockState(entityIn.getPosition()))
|| AllBlocks.BELT.typeOf(world.getBlockState(entityIn.getPosition().down())));
if (movedPastEndingSlope && !movingDown && Math.abs(movementSpeed) > 0)
entityIn.setPosition(entityIn.posX, entityIn.posY + movement.y, entityIn.posZ);
if (movedPastEndingSlope) {
entityIn.setMotion(movement);
entityIn.velocityChanged = true;
}
}
}

View file

@ -0,0 +1,119 @@
package com.simibubi.create.modules.contraptions.relays.belt;
import static net.minecraft.block.Block.makeCuboidShape;
import com.simibubi.create.foundation.utility.VoxelShaper;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
import net.minecraft.block.BlockState;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.Vec3i;
import net.minecraft.util.math.shapes.IBooleanFunction;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.util.math.shapes.VoxelShapes;
public class BeltShapes {
private static final VoxelShape SLOPE_BUILDING_BLOCK_X = makeCuboidShape(5, 5, 1, 11, 11, 15),
SLOPE_BUILDING_BLOCK_Z = makeCuboidShape(1, 5, 5, 15, 11, 11),
CASING_HORIZONTAL = makeCuboidShape(0, 0, 0, 16, 11, 16);
private static final VoxelShaper SLOPE_END = VoxelShaper.forHorizontal(makeCuboidShape(1, 3, 0, 15, 13, 10)),
SLOPE_TOP_END = VoxelShaper.forHorizontal(
VoxelShapes.or(SLOPE_END.get(Direction.SOUTH), createHalfSlope(Direction.SOUTH, false))),
SLOPE_BOTTOM_END = VoxelShaper.forHorizontal(
VoxelShapes.or(SLOPE_END.get(Direction.SOUTH), createHalfSlope(Direction.SOUTH, true))),
FLAT_STRAIGHT = VoxelShaper.forHorizontalAxis(makeCuboidShape(0, 3, 1, 16, 13, 15)),
VERTICAL_STRAIGHT = VoxelShaper.forHorizontalAxis(makeCuboidShape(1, 0, 3, 15, 16, 13)),
SLOPE_STRAIGHT = VoxelShaper.forHorizontal(createSlope(Direction.SOUTH)),
CASING_TOP_END = VoxelShaper.forHorizontal(makeCuboidShape(0, 0, 0, 16, 11, 11));
public static VoxelShape getShape(BlockState state) {
Direction facing = state.get(BeltBlock.HORIZONTAL_FACING);
Axis axis = facing.getAxis();
Axis perpendicularAxis = facing.rotateY().getAxis();
Part part = state.get(BeltBlock.PART);
Slope slope = state.get(BeltBlock.SLOPE);
if (slope == Slope.HORIZONTAL)
return FLAT_STRAIGHT.get(perpendicularAxis);
if (slope == Slope.VERTICAL)
return VERTICAL_STRAIGHT.get(axis);
if (part != Part.MIDDLE && part != Part.PULLEY) {
boolean upward = slope == Slope.UPWARD;
if (part == Part.START)
upward = !upward;
else
facing = facing.getOpposite();
return upward ? SLOPE_TOP_END.get(facing) : SLOPE_BOTTOM_END.get(facing);
}
if (slope == Slope.DOWNWARD)
facing = facing.getOpposite();
return SLOPE_STRAIGHT.get(facing);
}
public static VoxelShape getCasingShape(BlockState state) {
if (!state.get(BeltBlock.CASING))
return VoxelShapes.empty();
Direction facing = state.get(BeltBlock.HORIZONTAL_FACING);
Part part = state.get(BeltBlock.PART);
Slope slope = state.get(BeltBlock.SLOPE);
if (slope == Slope.HORIZONTAL)
return CASING_HORIZONTAL;
if (slope == Slope.VERTICAL)
return VoxelShapes.empty();
if (part != Part.MIDDLE) {
boolean upward = slope == Slope.UPWARD;
if (part == Part.START)
upward = !upward;
else
facing = facing.getOpposite();
return upward ? CASING_TOP_END.get(facing) : CASING_HORIZONTAL;
}
if (slope == Slope.DOWNWARD)
facing = facing.getOpposite();
return CASING_TOP_END.get(facing.getOpposite());
}
protected static VoxelShape createSlope(Direction facing) {
return VoxelShapes.or(createHalfSlope(facing.getOpposite(), false), createHalfSlope(facing, true));
}
protected static VoxelShape createHalfSlope(Direction facing, boolean upward) {
VoxelShape shape = VoxelShapes.empty();
VoxelShape buildingBlock = facing.getAxis() == Axis.X ? SLOPE_BUILDING_BLOCK_X : SLOPE_BUILDING_BLOCK_Z;
Vec3i directionVec = facing.getDirectionVec();
int x = directionVec.getX();
int y = upward ? 1 : -1;
int z = directionVec.getZ();
for (int segment = 0; segment < 6; segment++)
shape = VoxelShapes.or(shape,
buildingBlock.withOffset(x * segment / 16f, y * segment / 16f, z * segment / 16f));
if (!upward)
return shape;
VoxelShape mask = makeCuboidShape(0, -8, 0, 16, 24, 16);
for (int segment = 6; segment < 11; segment++)
shape = VoxelShapes.or(shape,
VoxelShapes.combine(mask,
buildingBlock.withOffset(x * segment / 16f, y * segment / 16f, z * segment / 16f),
IBooleanFunction.AND));
return shape;
}
}

View file

@ -1,5 +1,13 @@
package com.simibubi.create.modules.contraptions.relays.belt; package com.simibubi.create.modules.contraptions.relays.belt;
import static com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part.END;
import static com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part.MIDDLE;
import static com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope.DOWNWARD;
import static com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope.HORIZONTAL;
import static com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope.UPWARD;
import static net.minecraft.util.Direction.AxisDirection.NEGATIVE;
import static net.minecraft.util.Direction.AxisDirection.POSITIVE;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -9,114 +17,178 @@ import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllTileEntities; import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.utility.ColorHelper; import com.simibubi.create.foundation.utility.ColorHelper;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity; import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.BeltAttachmentState;
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.Tracker; import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.Tracker;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
import com.simibubi.create.modules.contraptions.relays.belt.BeltMovementHandler.TransportedEntityInfo;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.MoverType;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.DyeColor; import net.minecraft.item.DyeColor;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.NBTUtil; import net.minecraft.nbt.NBTUtil;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.Effects;
import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Direction.AxisDirection;
import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.Vec3i; import net.minecraft.util.math.Vec3i;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
public class BeltTileEntity extends KineticTileEntity { public class BeltTileEntity extends KineticTileEntity {
protected BlockPos controller;
public Map<Entity, TransportedEntityInfo> passengers; public Map<Entity, TransportedEntityInfo> passengers;
public AllBeltAttachments.Tracker attachmentTracker; public AllBeltAttachments.Tracker attachmentTracker;
private CompoundNBT trackerUpdateTag;
public int color; public int color;
public int beltLength;
public int index;
protected static class TransportedEntityInfo { protected BlockPos controller;
int ticksSinceLastCollision; protected BeltInventory inventory;
BlockPos lastCollidedPos; protected LazyOptional<IItemHandler> itemHandler;
BlockState lastCollidedState;
public TransportedEntityInfo(BlockPos collision, BlockState belt) { private CompoundNBT trackerUpdateTag;
refresh(collision, belt);
}
public void refresh(BlockPos collision, BlockState belt) {
ticksSinceLastCollision = 0;
lastCollidedPos = new BlockPos(collision).toImmutable();
lastCollidedState = belt;
}
public TransportedEntityInfo tick() {
ticksSinceLastCollision++;
return this;
}
}
public BeltTileEntity() { public BeltTileEntity() {
super(AllTileEntities.BELT.type); super(AllTileEntities.BELT.type);
controller = BlockPos.ZERO; controller = BlockPos.ZERO;
attachmentTracker = new Tracker(this); attachmentTracker = new Tracker(this);
itemHandler = LazyOptional.empty();
color = -1; color = -1;
beltLength = -1;
index = -1;
} }
protected boolean isLastBelt() { @Override
public void tick() {
super.tick();
// Initialize Belt Attachments
if (world != null && trackerUpdateTag != null) {
attachmentTracker.readAndSearch(trackerUpdateTag, this);
trackerUpdateTag = null;
}
if (getSpeed() == 0) if (getSpeed() == 0)
return false; return;
Direction direction = getBlockState().get(BlockStateProperties.HORIZONTAL_FACING); initializeItemHandler();
if (getBlockState().get(BeltBlock.SLOPE) == Slope.VERTICAL)
return false;
Part part = getBlockState().get(BeltBlock.PART); // Move Items
if (part == Part.MIDDLE) if (!isController())
return false; return;
getInventory().tick();
boolean movingPositively = (getSpeed() > 0 == (direction.getAxisDirection().getOffset() == 1)) // Move Entities
^ direction.getAxis() == Axis.X; if (passengers == null)
return part == Part.START ^ movingPositively; passengers = new HashMap<>();
List<Entity> toRemove = new ArrayList<>();
passengers.forEach((entity, info) -> {
boolean canBeTransported = BeltMovementHandler.canBeTransported(entity);
boolean leftTheBelt = info.ticksSinceLastCollision > ((getBlockState().get(BeltBlock.SLOPE) != HORIZONTAL)
? 3
: 1);
if (!canBeTransported || leftTheBelt) {
toRemove.add(entity);
return;
}
info.tick();
BeltMovementHandler.transportEntity(this, entity, info);
});
toRemove.forEach(passengers::remove);
}
@Override
public AxisAlignedBB getRenderBoundingBox() {
if (!isController())
return super.getRenderBoundingBox();
return super.getRenderBoundingBox().grow(beltLength);
}
protected void initializeItemHandler() {
if (world.isRemote || itemHandler.isPresent())
return;
if (!world.isBlockPresent(controller))
return;
TileEntity te = world.getTileEntity(controller);
if (te == null || !(te instanceof BeltTileEntity))
return;
IItemHandler handler = ((BeltTileEntity) te).getInventory().createHandlerForSegment(index);
itemHandler = LazyOptional.of(() -> handler);
}
@Override
public boolean hasFastRenderer() {
return !isController();
}
@Override
public <T> LazyOptional<T> getCapability(Capability<T> cap, Direction side) {
if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
if (side == Direction.UP || BeltBlock.canAccessFromSide(side, getBlockState())) {
return itemHandler.cast();
}
}
return super.getCapability(cap, side);
}
@Override
public void remove() {
super.remove();
itemHandler.invalidate();
} }
@Override @Override
public CompoundNBT write(CompoundNBT compound) { public CompoundNBT write(CompoundNBT compound) {
attachmentTracker.write(compound);
compound.put("Controller", NBTUtil.writeBlockPos(controller)); compound.put("Controller", NBTUtil.writeBlockPos(controller));
compound.putInt("Color", color); compound.putInt("Color", color);
attachmentTracker.write(compound); compound.putInt("Length", beltLength);
compound.putInt("Index", index);
if (isController())
compound.put("Inventory", getInventory().write());
return super.write(compound); return super.write(compound);
} }
@Override @Override
public void read(CompoundNBT compound) { public void read(CompoundNBT compound) {
controller = NBTUtil.readBlockPos(compound.getCompound("Controller"));
trackerUpdateTag = compound; trackerUpdateTag = compound;
controller = NBTUtil.readBlockPos(compound.getCompound("Controller"));
color = compound.getInt("Color"); color = compound.getInt("Color");
beltLength = compound.getInt("Length");
index = compound.getInt("Index");
if (isController())
getInventory().read(compound.getCompound("Inventory"));
super.read(compound); super.read(compound);
} }
public void applyColor(DyeColor colorIn) { public void applyColor(DyeColor colorIn) {
int colorValue = colorIn.getMapColor().colorValue; int colorValue = colorIn.getMapColor().colorValue;
for (BlockPos blockPos : BeltBlock.getBeltChain(world, getController())) { for (BlockPos blockPos : BeltBlock.getBeltChain(world, getController())) {
BeltTileEntity tileEntity = (BeltTileEntity) world.getTileEntity(blockPos); BeltTileEntity belt = (BeltTileEntity) world.getTileEntity(blockPos);
if (tileEntity != null) { if (belt == null)
if (tileEntity.color == -1) { continue;
tileEntity.color = colorValue; belt.color = belt.color == -1 ? colorValue : ColorHelper.mixColors(belt.color, colorValue, .5f);
} else { belt.markDirty();
tileEntity.color = ColorHelper.mixColors(tileEntity.color, colorValue, .5f); belt.sendData();
}
tileEntity.sendData();
} }
} }
public BeltTileEntity getControllerTE() {
if (!world.isBlockPresent(controller))
return null;
TileEntity te = world.getTileEntity(controller);
if (te == null || !(te instanceof BeltTileEntity))
return null;
return (BeltTileEntity) te;
} }
public void setController(BlockPos controller) { public void setController(BlockPos controller) {
@ -131,177 +203,123 @@ public class BeltTileEntity extends KineticTileEntity {
return controller.equals(pos); return controller.equals(pos);
} }
public float getBeltMovementSpeed() {
return getSpeed() / 1600f;
}
public float getDirectionAwareBeltMovementSpeed() {
int offset = getBeltFacing().getAxisDirection().getOffset();
if (getBeltFacing().getAxis() == Axis.X)
offset *= -1;
return getSpeed() / 1600f * offset;
}
public boolean hasPulley() { public boolean hasPulley() {
if (!AllBlocks.BELT.typeOf(getBlockState())) if (!AllBlocks.BELT.typeOf(getBlockState()))
return false; return false;
return getBlockState().get(BeltBlock.PART) == Part.END || getBlockState().get(BeltBlock.PART) == Part.START; return getBlockState().get(BeltBlock.PART) != Part.MIDDLE;
} }
@Override protected boolean isLastBelt() {
public void tick() {
super.tick();
if (world != null && trackerUpdateTag != null) {
attachmentTracker.readAndSearch(trackerUpdateTag, this);
trackerUpdateTag = null;
}
if (!isController())
return;
if (passengers == null)
passengers = new HashMap<>();
passengers.forEach((entity, info) -> {
transportEntity(entity, info);
});
List<Entity> toRemove = new ArrayList<>();
passengers.forEach((entity, info) -> {
if (!canTransport(entity))
toRemove.add(entity);
if (info.ticksSinceLastCollision > ((getBlockState().get(BeltBlock.SLOPE) != Slope.HORIZONTAL) ? 3 : 1)) {
toRemove.add(entity);
}
info.tick();
});
toRemove.forEach(e -> {
if (e instanceof ItemEntity)
((ItemEntity) e).setAgeToCreativeDespawnTime();
passengers.remove(e);
});
if (getSpeed() == 0) if (getSpeed() == 0)
return; return false;
Direction direction = getBeltFacing();
if (getBlockState().get(BeltBlock.SLOPE) == Slope.VERTICAL)
return false;
Part part = getBlockState().get(BeltBlock.PART);
if (part == MIDDLE)
return false;
boolean movingPositively = (getSpeed() > 0 == (direction.getAxisDirection().getOffset() == 1))
^ direction.getAxis() == Axis.X;
return part == Part.START ^ movingPositively;
} }
public void transportEntity(Entity entityIn, TransportedEntityInfo info) { public Vec3i getMovementDirection(boolean firstHalf) {
BlockPos pos = info.lastCollidedPos; return this.getMovementDirection(firstHalf, false);
TileEntity te = world.getTileEntity(pos);
TileEntity tileEntityBelowPassenger = world.getTileEntity(entityIn.getPosition());
BlockState blockState = info.lastCollidedState;
Direction movementFacing = Direction.getFacingFromAxisDirection(
blockState.get(BlockStateProperties.HORIZONTAL_FACING).getAxis(),
getSpeed() < 0 ? AxisDirection.POSITIVE : AxisDirection.NEGATIVE);
boolean collidedWithBelt = te instanceof BeltTileEntity;
boolean betweenBelts = tileEntityBelowPassenger instanceof BeltTileEntity && tileEntityBelowPassenger != te;
// Don't fight other Belts
if (!collidedWithBelt || betweenBelts) {
return;
} }
// Too slow public Vec3i getBeltChainDirection() {
boolean notHorizontal = getBlockState().get(BeltBlock.SLOPE) != Slope.HORIZONTAL; return this.getMovementDirection(true, true);
if (Math.abs(getSpeed()) < (notHorizontal ? 32 : 1))
return;
// Not on top
if (entityIn.posY - .25f < pos.getY())
return;
// Lock entities in place
if (entityIn instanceof LivingEntity && !(entityIn instanceof PlayerEntity)) {
((LivingEntity) entityIn).addPotionEffect(new EffectInstance(Effects.SLOWNESS, 1, 9, false, false));
} }
BeltTileEntity belt = (BeltTileEntity) te; protected Vec3i getMovementDirection(boolean firstHalf, boolean ignoreHalves) {
if (getSpeed() == 0)
// Attachment pauses movement return BlockPos.ZERO;
for (BeltAttachmentState state : belt.attachmentTracker.attachments) {
if (state.attachment.handleEntity(belt, entityIn, state)) {
info.ticksSinceLastCollision--;
return;
}
}
final BlockState blockState = getBlockState();
final Direction beltFacing = blockState.get(BlockStateProperties.HORIZONTAL_FACING); final Direction beltFacing = blockState.get(BlockStateProperties.HORIZONTAL_FACING);
final Slope slope = blockState.get(BeltBlock.SLOPE); final Slope slope = blockState.get(BeltBlock.SLOPE);
final Part part = blockState.get(BeltBlock.PART);
final Axis axis = beltFacing.getAxis(); final Axis axis = beltFacing.getAxis();
float movementSpeed = ((KineticTileEntity) te).getSpeed() / 1600f;
final Direction movementDirection = Direction
.getFacingFromAxis(axis == Axis.X ? AxisDirection.NEGATIVE : AxisDirection.POSITIVE, axis);
Vec3i centeringDirection = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis == Axis.X ? Axis.Z : Axis.X) Direction movementFacing = Direction.getFacingFromAxis(axis == Axis.X ? NEGATIVE : POSITIVE, axis);
.getDirectionVec(); boolean notHorizontal = blockState.get(BeltBlock.SLOPE) != HORIZONTAL;
Vec3d movement = new Vec3d(movementDirection.getDirectionVec()).scale(movementSpeed); if (getSpeed() < 0)
movementFacing = movementFacing.getOpposite();
Vec3i movement = movementFacing.getDirectionVec();
double diffCenter = axis == Axis.Z ? (pos.getX() + .5f - entityIn.posX) : (pos.getZ() + .5f - entityIn.posZ); boolean slopeBeforeHalf = (part == END) == (beltFacing.getAxisDirection() == POSITIVE);
float maxDiffCenter = (entityIn instanceof ItemEntity) ? 32 / 64f : 48 / 64f; boolean onSlope = notHorizontal && (part == MIDDLE || slopeBeforeHalf == firstHalf || ignoreHalves);
if (Math.abs(diffCenter) > maxDiffCenter) boolean movingUp = onSlope && slope == (movementFacing == beltFacing ? UPWARD : DOWNWARD);
return;
Part part = blockState.get(BeltBlock.PART); if (!onSlope)
float top = 13 / 16f; return movement;
boolean onSlope = notHorizontal && (part == Part.MIDDLE
|| part == (slope == Slope.UPWARD ? Part.END : Part.START) && entityIn.posY - pos.getY() < top
|| part == (slope == Slope.UPWARD ? Part.START : Part.END) && entityIn.posY - pos.getY() > top);
boolean movingDown = onSlope && slope == (movementFacing == beltFacing ? Slope.DOWNWARD : Slope.UPWARD); return new Vec3i(movement.getX(), movingUp ? 1 : -1, movement.getZ());
boolean movingUp = onSlope && slope == (movementFacing == beltFacing ? Slope.UPWARD : Slope.DOWNWARD);
if (beltFacing.getAxis() == Axis.Z) {
boolean b = movingDown;
movingDown = movingUp;
movingUp = b;
} }
if (movingUp) public Direction getMovementFacing() {
movement = movement.add(0, Math.abs(axis.getCoordinate(movement.x, movement.y, movement.z)), 0); return Direction.getFacingFromAxisDirection(getBeltFacing().getAxis(),
if (movingDown) getBeltMovementSpeed() < 0 ? POSITIVE : NEGATIVE);
movement = movement.add(0, -Math.abs(axis.getCoordinate(movement.x, movement.y, movement.z)), 0);
Vec3d centering = new Vec3d(centeringDirection).scale(diffCenter * Math.min(Math.abs(movementSpeed), .1f) * 4);
movement = movement.add(centering);
float step = entityIn.stepHeight;
if (!(entityIn instanceof PlayerEntity))
entityIn.stepHeight = 1;
// Entity Collisions
if (Math.abs(movementSpeed) < .5f) {
Vec3d checkDistance = movement.scale(2f).add(movement.normalize());
AxisAlignedBB bb = entityIn.getBoundingBox();
AxisAlignedBB checkBB = new AxisAlignedBB(bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ);
if (!world
.getEntitiesWithinAABBExcludingEntity(entityIn, checkBB.offset(checkDistance)
.grow(-Math.abs(checkDistance.x), -Math.abs(checkDistance.y), -Math.abs(checkDistance.z)))
.isEmpty()) {
entityIn.setMotion(0, 0, 0);
info.ticksSinceLastCollision--;
return;
}
} }
if (movingUp) { protected Direction getBeltFacing() {
float minVelocity = entityIn instanceof ItemEntity ? .09f : .13f; return getBlockState().get(BlockStateProperties.HORIZONTAL_FACING);
float yMovement = (float) -(Math.max(Math.abs(movement.y), minVelocity));
entityIn.move(MoverType.SELF, new Vec3d(0, yMovement, 0));
entityIn.move(MoverType.SELF, movement.mul(1, 0, 1));
} else if (movingDown) {
entityIn.move(MoverType.SELF, movement.mul(1, 0, 1));
entityIn.move(MoverType.SELF, movement.mul(0, 1, 0));
} else {
entityIn.move(MoverType.SELF, movement);
} }
if (!(entityIn instanceof PlayerEntity)) public BeltInventory getInventory() {
entityIn.stepHeight = step; if (inventory == null)
inventory = new BeltInventory(this);
boolean movedPastEndingSlope = onSlope && (AllBlocks.BELT.typeOf(world.getBlockState(entityIn.getPosition())) return inventory;
|| AllBlocks.BELT.typeOf(world.getBlockState(entityIn.getPosition().down())));
if (movedPastEndingSlope && !movingDown && Math.abs(movementSpeed) > 0)
entityIn.setPosition(entityIn.posX, entityIn.posY + movement.y, entityIn.posZ);
if (movedPastEndingSlope)
entityIn.setMotion(movement);
} }
public boolean canTransport(Entity entity) { public boolean tryInsertingFromSide(Direction side, ItemStack stack, boolean simulate) {
if (!entity.isAlive()) return tryInsertingFromSide(side, new TransportedItemStack(stack), simulate);
return false; }
if (entity instanceof PlayerEntity && ((PlayerEntity) entity).isSneaking())
public boolean tryInsertingFromSide(Direction side, TransportedItemStack transportedStack, boolean simulate) {
BeltTileEntity nextBeltController = getControllerTE();
if (nextBeltController == null)
return false; return false;
BeltInventory nextInventory = nextBeltController.getInventory();
if (!nextInventory.canInsertFrom(index, side))
return false;
if (simulate)
return true;
transportedStack.beltPosition = index + .5f;
Direction movementFacing = getMovementFacing();
if (!side.getAxis().isVertical()) {
if (movementFacing != side)
transportedStack.sideOffset = side.getAxisDirection().getOffset() * .35f;
else
transportedStack.beltPosition = getDirectionAwareBeltMovementSpeed() > 0 ? index : index + 1;
if (side.getAxis() == Axis.X ^ movementFacing.getAxis() == Axis.X)
transportedStack.sideOffset *= -1;
}
transportedStack.prevSideOffset = transportedStack.sideOffset;
transportedStack.insertedAt = index;
transportedStack.insertedFrom = side;
transportedStack.prevBeltPosition = transportedStack.beltPosition;
nextInventory.insert(transportedStack);
nextBeltController.markDirty();
nextBeltController.sendData();
return true; return true;
} }

View file

@ -1,114 +1,159 @@
package com.simibubi.create.modules.contraptions.relays.belt; package com.simibubi.create.modules.contraptions.relays.belt;
import java.nio.ByteBuffer; import java.util.Random;
import com.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.Create; import com.simibubi.create.foundation.utility.IndependentShadowRenderer;
import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.TessellatorHelper;
import com.simibubi.create.foundation.utility.BufferManipulator;
import com.simibubi.create.modules.contraptions.base.IRotate; import com.simibubi.create.modules.contraptions.base.IRotate;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity; import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer.BlockModelSpinner;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.texture.AtlasTexture; import net.minecraft.client.renderer.ItemRenderer;
import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType;
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.Vec3i;
public class BeltTileEntityRenderer extends KineticTileEntityRenderer { @SuppressWarnings("deprecation")
public class BeltTileEntityRenderer extends TileEntityRenderer<BeltTileEntity> {
protected static class BeltModelAnimator extends BufferManipulator { @Override
protected static TextureAtlasSprite beltTextures; public void render(BeltTileEntity te, double x, double y, double z, float partialTicks, int destroyStage) {
protected static TextureAtlasSprite originalTexture; super.render(te, x, y, z, partialTicks, destroyStage);
public BeltModelAnimator(ByteBuffer template) { TessellatorHelper.prepareFastRender();
super(template); TessellatorHelper.begin(DefaultVertexFormats.BLOCK);
if (beltTextures == null) renderTileEntityFast(te, x, y, z, partialTicks, destroyStage, Tessellator.getInstance().getBuffer());
initSprites(); TessellatorHelper.draw();
if (te.isController()) {
GlStateManager.pushMatrix();
Vec3i directionVec = te.getBeltFacing().getDirectionVec();
Vec3d beltStartOffset = new Vec3d(directionVec).scale(-.5).add(.5, 13 / 16f + .125f, .5);
GlStateManager.translated(x + beltStartOffset.x, y + beltStartOffset.y, z + beltStartOffset.z);
Slope slope = te.getBlockState().get(BeltBlock.SLOPE);
int verticality = slope == Slope.DOWNWARD ? -1 : slope == Slope.UPWARD ? 1 : 0;
boolean slopeAlongX = te.getBeltFacing().getAxis() == Axis.X;
for (TransportedItemStack transported : te.getInventory().items) {
GlStateManager.pushMatrix();
float offset = MathHelper.lerp(partialTicks, transported.prevBeltPosition, transported.beltPosition);
float sideOffset = MathHelper.lerp(partialTicks, transported.prevSideOffset, transported.sideOffset);
float verticalMovement = verticality;
if (te.getSpeed() == 0) {
offset = transported.beltPosition;
sideOffset = transported.sideOffset;
} }
private void initSprites() { if (offset < .5)
AtlasTexture textureMap = Minecraft.getInstance().getTextureMap(); verticalMovement = 0;
originalTexture = textureMap.getSprite(new ResourceLocation(Create.ID, "block/belt")); verticalMovement = verticalMovement * (Math.min(offset, te.beltLength - .5f) - .5f);
beltTextures = textureMap.getSprite(new ResourceLocation(Create.ID, "block/belt_animated")); Vec3d offsetVec = new Vec3d(directionVec).scale(offset).add(0, verticalMovement, 0);
boolean onSlope = slope != Slope.HORIZONTAL
&& MathHelper.clamp(offset, .5f, te.beltLength - .5f) == offset;
float slopeAngle = onSlope
? slope == Slope.DOWNWARD ^ te.getDirectionAwareBeltMovementSpeed() > 0
^ te.getBeltMovementSpeed() < 0 ? -45 : 45
: 0;
GlStateManager.translated(offsetVec.x, offsetVec.y, offsetVec.z);
boolean alongX = te.getBeltFacing().rotateY().getAxis() == Axis.X;
if (!alongX)
sideOffset *= -1;
GlStateManager.translated(alongX ? sideOffset : 0, 0, alongX ? 0 : sideOffset);
ItemRenderer itemRenderer = Minecraft.getInstance().getItemRenderer();
boolean blockItem = itemRenderer.getModelWithOverrides(transported.stack).isGui3d();
if (Minecraft.getInstance().gameSettings.fancyGraphics) {
Vec3d shadowPos = new Vec3d(te.getPos()).add(beltStartOffset.scale(1).add(offsetVec)
.add(alongX ? sideOffset : 0, .39, alongX ? 0 : sideOffset));
IndependentShadowRenderer.renderShadow(shadowPos.x, shadowPos.y, shadowPos.z, .75f,
blockItem ? .2f : .2f);
} }
public ByteBuffer getTransformed(BeltTileEntity te, float x, float y, float z, int color) { RenderHelper.enableStandardItemLighting();
original.rewind();
mutable.rewind();
float textureOffsetX = 0; int count = (int) (MathHelper.log2((int) (transported.stack.getCount()))) / 2;
float textureOffsetY = 0; GlStateManager.rotated(slopeAngle, slopeAlongX ? 0 : 1, 0, slopeAlongX ? 1 : 0);
if (onSlope)
GlStateManager.translated(0, 1 / 8f, 0);
Random r = new Random(transported.angle);
if (te.getSpeed() != 0) { for (int i = 0; i <= count; i++) {
float time = AnimationTickHolder.getRenderTick(); GlStateManager.pushMatrix();
Direction direction = te.getBlockState().get(BlockStateProperties.HORIZONTAL_FACING);
if (direction == Direction.EAST || direction == Direction.NORTH)
time = -time;
int textureIndex = (int) ((te.getSpeed() * time / 8) % 16);
if (textureIndex < 0)
textureIndex += 16;
textureOffsetX = beltTextures.getInterpolatedU((textureIndex % 4) * 4) - originalTexture.getMinU(); GlStateManager.rotated(transported.angle, 0, 1, 0);
textureOffsetY = beltTextures.getInterpolatedV((textureIndex / 4) * 4) - originalTexture.getMinV(); if (!blockItem) {
GlStateManager.translated(0, -.09375, 0);
GlStateManager.rotated(90, 1, 0, 0);
} }
final BlockState blockState = te.getBlockState(); if (blockItem) {
int packedLightCoords = blockState.getPackedLightmapCoords(te.getWorld(), te.getPos()); GlStateManager.translated(r.nextFloat() * .25f, 0, r.nextFloat() * .25f);
float texOffX = textureOffsetX;
float texOffY = textureOffsetY;
boolean defaultColor = color == -1;
int b = defaultColor ? 128 : color & 0xFF;
int g = defaultColor ? 128 : (color >> 8) & 0xFF;
int r = defaultColor ? 128 : (color >> 16) & 0xFF;
for (int vertex = 0; vertex < vertexCount(original); vertex++) {
putPos(mutable, vertex, getX(original, vertex) + x, getY(original, vertex) + y,
getZ(original, vertex) + z);
putLight(mutable, vertex, packedLightCoords);
int bufferPosition = getBufferPosition(vertex);
mutable.putFloat(bufferPosition + 16, original.getFloat(bufferPosition + 16) + texOffX);
mutable.putFloat(bufferPosition + 20, original.getFloat(bufferPosition + 20) + texOffY);
byte lumByte = getR(original, vertex);
float lum = (lumByte < 0 ? 255 + lumByte : lumByte) / 256f;
int r2 = (int) (r * lum);
int g2 = (int) (g * lum);
int b2 = (int) (b * lum);
putColor(mutable, vertex, (byte) r2, (byte) g2, (byte) b2, (byte) 255);
} }
return mutable; GlStateManager.scaled(.5, .5, .5);
itemRenderer.renderItem(transported.stack, TransformType.FIXED);
GlStateManager.popMatrix();
if (!blockItem)
GlStateManager.rotated(10, 0, 1, 0);
GlStateManager.translated(0, blockItem ? 1 / 64d : 1 / 16d, 0);
}
RenderHelper.disableStandardItemLighting();
GlStateManager.popMatrix();
}
GlStateManager.popMatrix();
} }
} }
@Override @Override
public void renderTileEntityFast(KineticTileEntity te, double x, double y, double z, float partialTicks, public void renderTileEntityFast(BeltTileEntity te, double x, double y, double z, float partialTicks,
int destroyStage, BufferBuilder buffer) { int destroyStage, BufferBuilder buffer) {
BeltTileEntity beltEntity = (BeltTileEntity) te;
if (beltEntity.hasPulley()) if (te.hasPulley()) {
super.renderTileEntityFast(te, x, y, z, partialTicks, destroyStage, buffer); final BlockState state = getRenderedBlockState(te);
KineticTileEntityRenderer.cacheIfMissing(state, getWorld(), BlockModelSpinner::new);
cacheIfMissing(beltEntity.getBlockState(), getWorld(), BeltModelAnimator::new); final BlockPos pos = te.getPos();
renderBeltFromCache(beltEntity, (float) x, (float) y, (float) z, buffer); Axis axis = ((IRotate) te.getBlockState().getBlock()).getRotationAxis(te.getBlockState());
float angle = KineticTileEntityRenderer.getAngleForTe(te, pos, axis);
KineticTileEntityRenderer.renderFromCache(buffer, state, getWorld(), (float) x, (float) y, (float) z, pos,
axis, angle);
}
KineticTileEntityRenderer.cacheIfMissing(te.getBlockState().with(BeltBlock.CASING, false), getWorld(),
BeltModelAnimator::new);
renderBeltFromCache(te, (float) x, (float) y, (float) z, buffer);
} }
@Override
protected BlockState getRenderedBlockState(KineticTileEntity te) { protected BlockState getRenderedBlockState(KineticTileEntity te) {
return AllBlocks.BELT_PULLEY.get().getDefaultState().with(BlockStateProperties.AXIS, return AllBlocks.BELT_PULLEY.get().getDefaultState().with(BlockStateProperties.AXIS,
((IRotate) AllBlocks.BELT.get()).getRotationAxis(te.getBlockState())); ((IRotate) AllBlocks.BELT.get()).getRotationAxis(te.getBlockState()));
} }
public void renderBeltFromCache(BeltTileEntity te, float x, float y, float z, BufferBuilder buffer) { public void renderBeltFromCache(BeltTileEntity te, float x, float y, float z, BufferBuilder buffer) {
buffer.putBulkData( buffer.putBulkData(((BeltModelAnimator) KineticTileEntityRenderer.cachedBuffers
((BeltModelAnimator) cachedBuffers.get(te.getBlockState())).getTransformed(te, x, y, z, te.color)); .get(te.getBlockState().with(BeltBlock.CASING, false))).getTransformed(te, x, y, z, te.color));
} }
} }

View file

@ -0,0 +1,69 @@
package com.simibubi.create.modules.contraptions.relays.belt;
import net.minecraft.item.ItemStack;
import net.minecraftforge.items.IItemHandler;
public class ItemHandlerBeltSegment implements IItemHandler {
private final BeltInventory beltInventory;
int offset;
public ItemHandlerBeltSegment(BeltInventory beltInventory, int offset) {
this.beltInventory = beltInventory;
this.offset = offset;
}
@Override
public int getSlots() {
return 1;
}
@Override
public ItemStack getStackInSlot(int slot) {
TransportedItemStack stackAtOffset = this.beltInventory.getStackAtOffset(offset);
if (stackAtOffset == null)
return ItemStack.EMPTY;
return stackAtOffset.stack;
}
@Override
public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) {
if (this.beltInventory.canInsertAt(offset)) {
if (!simulate) {
TransportedItemStack newStack = new TransportedItemStack(stack);
newStack.insertedAt = offset;
newStack.beltPosition = offset + .5f;
newStack.prevBeltPosition = newStack.beltPosition;
this.beltInventory.insert(newStack);
}
return ItemStack.EMPTY;
}
return stack;
}
@Override
public ItemStack extractItem(int slot, int amount, boolean simulate) {
TransportedItemStack transported = this.beltInventory.getStackAtOffset(offset);
if (transported == null)
return ItemStack.EMPTY;
amount = Math.min(amount, transported.stack.getCount());
ItemStack extracted = simulate ? transported.stack.copy().split(amount) : transported.stack.split(amount);
if (!simulate) {
this.beltInventory.belt.markDirty();
this.beltInventory.belt.sendData();
}
return extracted;
}
@Override
public int getSlotLimit(int slot) {
return Math.min(getStackInSlot(slot).getMaxStackSize(), 64);
}
@Override
public boolean isItemValid(int slot, ItemStack stack) {
return true;
}
}

View file

@ -0,0 +1,87 @@
package com.simibubi.create.modules.contraptions.relays.belt;
import java.util.Random;
import com.simibubi.create.modules.logistics.InWorldProcessing;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.Direction;
public class TransportedItemStack implements Comparable<TransportedItemStack> {
public ItemStack stack;
public float beltPosition;
public float sideOffset;
public int angle;
public int insertedAt;
public Direction insertedFrom;
public boolean locked;
public float prevBeltPosition;
public float prevSideOffset;
public InWorldProcessing.Type processedBy;
public int processingTime;
public TransportedItemStack(ItemStack stack) {
this.stack = stack;
angle = new Random().nextInt(360);
sideOffset = prevSideOffset = getTargetSideOffset();
insertedFrom = Direction.UP;
}
public float getTargetSideOffset() {
return (angle - 180) / (360 * 3f);
}
@Override
public int compareTo(TransportedItemStack o) {
return beltPosition < o.beltPosition ? 1 : beltPosition > o.beltPosition ? -1 : 0;
}
public TransportedItemStack getSimilar() {
TransportedItemStack copy = new TransportedItemStack(stack.copy());
copy.beltPosition = beltPosition;
copy.insertedAt = insertedAt;
copy.insertedFrom = insertedFrom;
copy.prevBeltPosition = prevBeltPosition;
copy.prevSideOffset = prevSideOffset;
copy.processedBy = processedBy;
copy.processingTime = processingTime;
return copy;
}
public TransportedItemStack copy() {
TransportedItemStack copy = getSimilar();
copy.angle = angle;
return copy;
}
public CompoundNBT serializeNBT() {
CompoundNBT nbt = new CompoundNBT();
nbt.put("Item", stack.serializeNBT());
nbt.putFloat("Pos", beltPosition);
nbt.putFloat("PrevPos", prevBeltPosition);
nbt.putFloat("Offset", sideOffset);
nbt.putFloat("PrevOffset", prevSideOffset);
nbt.putInt("InSegment", insertedAt);
nbt.putInt("Angle", angle);
nbt.putInt("InDirection", insertedFrom.getIndex());
nbt.putBoolean("Locked", locked);
return nbt;
}
public static TransportedItemStack read(CompoundNBT nbt) {
TransportedItemStack stack = new TransportedItemStack(ItemStack.read(nbt.getCompound("Item")));
stack.beltPosition = nbt.getFloat("Pos");
stack.prevBeltPosition = nbt.getFloat("PrevPos");
stack.sideOffset = nbt.getFloat("Offset");
stack.prevSideOffset = nbt.getFloat("PrevOffset");
stack.insertedAt = nbt.getInt("InSegment");
stack.angle = nbt.getInt("Angle");
stack.insertedFrom = Direction.byIndex(nbt.getInt("InDirection"));
stack.locked = nbt.getBoolean("Locked");
return stack;
}
}

View file

@ -64,7 +64,7 @@ public class WindowInABlockTileEntity extends SyncedTileEntity {
windowBlock = getWindowBlock().updatePostPlacement(side, world.getBlockState(offsetPos), world, pos, windowBlock = getWindowBlock().updatePostPlacement(side, world.getBlockState(offsetPos), world, pos,
offsetPos); offsetPos);
} }
sendData(); world.notifyBlockUpdate(getPos(), getBlockState(), getBlockState(), 2 | 16);
markDirty(); markDirty();
} }

View file

@ -1,13 +1,17 @@
package com.simibubi.create.modules.logistics; package com.simibubi.create.modules.logistics;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import com.simibubi.create.AllRecipes; import com.simibubi.create.AllRecipes;
import com.simibubi.create.CreateConfig; import com.simibubi.create.CreateConfig;
import com.simibubi.create.foundation.utility.ItemHelper; import com.simibubi.create.foundation.utility.ItemHelper;
import com.simibubi.create.modules.contraptions.base.ProcessingRecipe;
import com.simibubi.create.modules.contraptions.receivers.SplashingRecipe; import com.simibubi.create.modules.contraptions.receivers.SplashingRecipe;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.TransportedItemStack;
import net.minecraft.entity.item.ItemEntity; import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
@ -40,12 +44,27 @@ public class InWorldProcessing {
} }
public static boolean canProcess(ItemEntity entity, Type type) { public static boolean canProcess(ItemEntity entity, Type type) {
World world = entity.world; if (entity.getPersistentData().contains("CreateData")) {
CompoundNBT compound = entity.getPersistentData().getCompound("CreateData");
if (compound.contains("Processing")) {
CompoundNBT processing = compound.getCompound("Processing");
if (entity.getPersistentData().contains("CreateData") if (Type.valueOf(processing.getString("Type")) != type) {
&& entity.getPersistentData().getCompound("CreateData").contains("Processing")) boolean canProcess = canProcess(entity.getItem(), type, entity.world);
processing.putString("Type", type.name());
if (!canProcess)
processing.putInt("Time", -1);
return canProcess;
} else if (processing.getInt("Time") >= 0)
return true; return true;
else if (processing.getInt("Time") == -1)
return false;
}
}
return canProcess(entity.getItem(), type, entity.world);
}
private static boolean canProcess(ItemStack stack, Type type, World world) {
if (type == Type.BLASTING) { if (type == Type.BLASTING) {
return true; return true;
} }
@ -53,13 +72,13 @@ public class InWorldProcessing {
if (type == Type.SMOKING) { if (type == Type.SMOKING) {
SmokerTileEntity smoker = new SmokerTileEntity(); SmokerTileEntity smoker = new SmokerTileEntity();
smoker.setWorld(world); smoker.setWorld(world);
smoker.setInventorySlotContents(0, entity.getItem()); smoker.setInventorySlotContents(0, stack);
Optional<SmokingRecipe> recipe = world.getRecipeManager().getRecipe(IRecipeType.SMOKING, smoker, world); Optional<SmokingRecipe> recipe = world.getRecipeManager().getRecipe(IRecipeType.SMOKING, smoker, world);
return recipe.isPresent(); return recipe.isPresent();
} }
if (type == Type.SPLASHING) { if (type == Type.SPLASHING) {
splashingInv.setInventorySlotContents(0, entity.getItem()); splashingInv.setInventorySlotContents(0, stack);
Optional<SplashingRecipe> recipe = world.getRecipeManager().getRecipe(AllRecipes.Types.SPLASHING, Optional<SplashingRecipe> recipe = world.getRecipeManager().getRecipe(AllRecipes.Types.SPLASHING,
splashingInv, world); splashingInv, world);
return recipe.isPresent(); return recipe.isPresent();
@ -68,59 +87,90 @@ public class InWorldProcessing {
return false; return false;
} }
public static void process(ItemEntity entity, Type type) { public static void applyProcessing(ItemEntity entity, Type type) {
World world = entity.world;
if (decrementProcessingTime(entity, type) != 0) if (decrementProcessingTime(entity, type) != 0)
return; return;
List<ItemStack> stacks = process(entity.getItem(), type, entity.world);
if (stacks == null)
return;
if (stacks.isEmpty()) {
entity.remove();
return;
}
entity.setItem(stacks.remove(0));
for (ItemStack additional : stacks) {
ItemEntity entityIn = new ItemEntity(entity.world, entity.posX, entity.posY, entity.posZ, additional);
entityIn.setMotion(entity.getMotion());
entity.world.addEntity(entityIn);
}
}
public static List<TransportedItemStack> applyProcessing(TransportedItemStack transported, BeltTileEntity belt, Type type) {
if (transported.processedBy != type) {
transported.processedBy = type;
transported.processingTime = CreateConfig.parameters.inWorldProcessingTime.get() + 1;
if (!canProcess(transported.stack, type, belt.getWorld()))
transported.processingTime = -1;
return null;
}
if (transported.processingTime == -1)
return null;
if (transported.processingTime-- > 0)
return null;
List<ItemStack> stacks = process(transported.stack, type, belt.getWorld());
List<TransportedItemStack> transportedStacks = new ArrayList<>();
for (ItemStack additional : stacks) {
TransportedItemStack newTransported = transported.getSimilar();
newTransported.stack = additional.copy();
transportedStacks.add(newTransported);
}
return transportedStacks;
}
private static List<ItemStack> process(ItemStack stack, Type type, World world) {
if (type == Type.SPLASHING) { if (type == Type.SPLASHING) {
splashingInv.setInventorySlotContents(0, entity.getItem()); splashingInv.setInventorySlotContents(0, stack);
Optional<SplashingRecipe> recipe = world.getRecipeManager().getRecipe(AllRecipes.Types.SPLASHING, Optional<SplashingRecipe> recipe = world.getRecipeManager().getRecipe(AllRecipes.Types.SPLASHING,
splashingInv, world); splashingInv, world);
if (recipe.isPresent()) if (recipe.isPresent())
applyRecipeOn(entity, recipe.get()); return applyRecipeOn(stack, recipe.get());
return; return null;
} }
SmokerTileEntity smoker = new SmokerTileEntity(); SmokerTileEntity smoker = new SmokerTileEntity();
smoker.setWorld(world); smoker.setWorld(world);
smoker.setInventorySlotContents(0, entity.getItem()); smoker.setInventorySlotContents(0, stack);
Optional<SmokingRecipe> smokingRecipe = world.getRecipeManager().getRecipe(IRecipeType.SMOKING, smoker, world); Optional<SmokingRecipe> smokingRecipe = world.getRecipeManager().getRecipe(IRecipeType.SMOKING, smoker, world);
if (type == Type.BLASTING) { if (type == Type.BLASTING) {
FurnaceTileEntity furnace = new FurnaceTileEntity(); FurnaceTileEntity furnace = new FurnaceTileEntity();
furnace.setWorld(world); furnace.setWorld(world);
furnace.setInventorySlotContents(0, entity.getItem()); furnace.setInventorySlotContents(0, stack);
Optional<FurnaceRecipe> smeltingRecipe = world.getRecipeManager().getRecipe(IRecipeType.SMELTING, furnace, Optional<FurnaceRecipe> smeltingRecipe = world.getRecipeManager().getRecipe(IRecipeType.SMELTING, furnace,
world); world);
if (!smokingRecipe.isPresent()) { if (!smokingRecipe.isPresent()) {
if (smeltingRecipe.isPresent()) { if (smeltingRecipe.isPresent())
applyRecipeOn(entity, smeltingRecipe.get()); return applyRecipeOn(stack, smeltingRecipe.get());
return;
}
BlastFurnaceTileEntity blastFurnace = new BlastFurnaceTileEntity(); BlastFurnaceTileEntity blastFurnace = new BlastFurnaceTileEntity();
blastFurnace.setWorld(world); blastFurnace.setWorld(world);
blastFurnace.setInventorySlotContents(0, entity.getItem()); blastFurnace.setInventorySlotContents(0, stack);
Optional<BlastingRecipe> blastingRecipe = world.getRecipeManager().getRecipe(IRecipeType.BLASTING, Optional<BlastingRecipe> blastingRecipe = world.getRecipeManager().getRecipe(IRecipeType.BLASTING,
blastFurnace, world); blastFurnace, world);
if (blastingRecipe.isPresent()) { if (blastingRecipe.isPresent())
applyRecipeOn(entity, blastingRecipe.get()); return applyRecipeOn(stack, blastingRecipe.get());
return;
}
} }
entity.remove(); return Collections.emptyList();
return;
} }
if (type == Type.SMOKING && smokingRecipe.isPresent()) { if (type == Type.SMOKING && smokingRecipe.isPresent())
applyRecipeOn(entity, smokingRecipe.get()); return applyRecipeOn(stack, smokingRecipe.get());
return;
}
return null;
} }
private static int decrementProcessingTime(ItemEntity entity, Type type) { private static int decrementProcessingTime(ItemEntity entity, Type type) {
@ -145,12 +195,29 @@ public class InWorldProcessing {
} }
public static void applyRecipeOn(ItemEntity entity, IRecipe<?> recipe) { public static void applyRecipeOn(ItemEntity entity, IRecipe<?> recipe) {
List<ItemStack> stacks = applyRecipeOn(entity.getItem(), recipe);
if (stacks == null)
return;
if (stacks.isEmpty()) {
entity.remove();
return;
}
entity.setItem(stacks.remove(0));
for (ItemStack additional : stacks) {
ItemEntity entityIn = new ItemEntity(entity.world, entity.posX, entity.posY, entity.posZ, additional);
entityIn.setMotion(entity.getMotion());
entity.world.addEntity(entityIn);
}
}
private static List<ItemStack> applyRecipeOn(ItemStack stackIn, IRecipe<?> recipe) {
List<ItemStack> stacks; List<ItemStack> stacks;
if (recipe instanceof SplashingRecipe) { if (recipe instanceof ProcessingRecipe) {
stacks = new ArrayList<>(); stacks = new ArrayList<>();
for (int i = 0; i < entity.getItem().getCount(); i++) { for (int i = 0; i < stackIn.getCount(); i++) {
for (ItemStack stack : ((SplashingRecipe) recipe).rollResults()) { List<ItemStack> rollResults = ((ProcessingRecipe<?>) recipe).rollResults();
for (ItemStack stack : rollResults) {
for (ItemStack previouslyRolled : stacks) { for (ItemStack previouslyRolled : stacks) {
if (stack.isEmpty()) if (stack.isEmpty())
continue; continue;
@ -170,19 +237,10 @@ public class InWorldProcessing {
} }
} else { } else {
ItemStack out = recipe.getRecipeOutput().copy(); ItemStack out = recipe.getRecipeOutput().copy();
stacks = ItemHelper.multipliedOutput(entity.getItem(), out); stacks = ItemHelper.multipliedOutput(stackIn, out);
} }
if (stacks.isEmpty()) { return stacks;
entity.remove();
return;
}
entity.setItem(stacks.remove(0));
for (ItemStack additional : stacks) {
ItemEntity entityIn = new ItemEntity(entity.world, entity.posX, entity.posY, entity.posZ, additional);
entityIn.setMotion(entity.getMotion());
entity.world.addEntity(entityIn);
}
} }
public static boolean isFrozen() { public static boolean isFrozen() {

View file

@ -2,8 +2,10 @@ package com.simibubi.create.modules.logistics.block;
import static net.minecraft.state.properties.BlockStateProperties.HORIZONTAL_FACING; import static net.minecraft.state.properties.BlockStateProperties.HORIZONTAL_FACING;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.CreateConfig; import com.simibubi.create.CreateConfig;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.logistics.item.CardboardBoxItem; import com.simibubi.create.modules.logistics.item.CardboardBoxItem;
import com.simibubi.create.modules.logistics.transport.CardboardBoxEntity; import com.simibubi.create.modules.logistics.transport.CardboardBoxEntity;
@ -11,10 +13,12 @@ import net.minecraft.entity.Entity;
import net.minecraft.entity.item.ItemEntity; import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.ITickableTileEntity; import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvents; import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
@ -119,13 +123,29 @@ public interface IExtractor extends ITickableTileEntity, IInventoryManipulator {
} }
default boolean hasSpaceForExtracting() { default boolean hasSpaceForExtracting() {
return getWorld().getEntitiesWithinAABBExcludingEntity(null, new AxisAlignedBB(getPos())).isEmpty(); BlockPos pos = getPos();
World world = getWorld();
if (AllBlocks.BELT.typeOf(world.getBlockState(pos.down()))) {
TileEntity te = world.getTileEntity(pos.down());
if (te != null && te instanceof BeltTileEntity) {
BeltTileEntity belt = (BeltTileEntity) te;
BeltTileEntity controller = belt.getControllerTE();
if (controller != null) {
if (!controller.getInventory().canInsertFrom(belt.index, Direction.UP))
return false;
}
}
}
return world.getEntitiesWithinAABBExcludingEntity(null, new AxisAlignedBB(getPos())).isEmpty();
} }
default ItemStack extract(boolean simulate) { default ItemStack extract(boolean simulate) {
IItemHandler inv = getInventory().orElse(null); IItemHandler inv = getInventory().orElse(null);
ItemStack extracting = ItemStack.EMPTY; ItemStack extracting = ItemStack.EMPTY;
ItemStack filterItem = (this instanceof IHaveFilter) ? ((IHaveFilter) this).getFilter() : ItemStack.EMPTY; ItemStack filterItem = (this instanceof IHaveFilter) ? ((IHaveFilter) this).getFilter() : ItemStack.EMPTY;
World world = getWorld();
int extractionCount = filterItem.isEmpty() ? CreateConfig.parameters.extractorAmount.get() int extractionCount = filterItem.isEmpty() ? CreateConfig.parameters.extractorAmount.get()
: filterItem.getCount(); : filterItem.getCount();
boolean checkHasEnoughItems = !filterItem.isEmpty(); boolean checkHasEnoughItems = !filterItem.isEmpty();
@ -172,17 +192,16 @@ public interface IExtractor extends ITickableTileEntity, IInventoryManipulator {
} while (true); } while (true);
if (!simulate && hasEnoughItems) { if (!simulate && hasEnoughItems) {
World world = getWorld(); Vec3d entityPos = VecHelper.getCenterOf(getPos()).add(0, -0.5f, 0);
Vec3d pos = VecHelper.getCenterOf(getPos()).add(0, -0.5f, 0);
Entity entityIn = null; Entity entityIn = null;
if (extracting.getItem() instanceof CardboardBoxItem) { if (extracting.getItem() instanceof CardboardBoxItem) {
Direction face = getWorld().getBlockState(getPos()).get(HORIZONTAL_FACING).getOpposite(); Direction face = getWorld().getBlockState(getPos()).get(HORIZONTAL_FACING).getOpposite();
entityIn = new CardboardBoxEntity(world, pos, extracting, face); entityIn = new CardboardBoxEntity(world, entityPos, extracting, face);
world.playSound(null, getPos(), SoundEvents.ENTITY_ITEM_PICKUP, SoundCategory.BLOCKS, .25f, .05f); world.playSound(null, getPos(), SoundEvents.ENTITY_ITEM_PICKUP, SoundCategory.BLOCKS, .25f, .05f);
} else { } else {
entityIn = new ItemEntity(world, pos.x, pos.y, pos.z, extracting); entityIn = new ItemEntity(world, entityPos.x, entityPos.y, entityPos.z, extracting);
entityIn.setMotion(Vec3d.ZERO); entityIn.setMotion(Vec3d.ZERO);
world.playSound(null, getPos(), SoundEvents.ENTITY_ITEM_PICKUP, SoundCategory.BLOCKS, .125f, .1f); world.playSound(null, getPos(), SoundEvents.ENTITY_ITEM_PICKUP, SoundCategory.BLOCKS, .125f, .1f);
} }

View file

@ -1,8 +1,8 @@
package com.simibubi.create.modules.logistics.block.belts; package com.simibubi.create.modules.logistics.block.belts;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Optional;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.block.IWithTileEntity; import com.simibubi.create.foundation.block.IWithTileEntity;
@ -10,22 +10,25 @@ import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.BeltAttachmentState; import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.BeltAttachmentState;
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.IBeltAttachment; import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.IBeltAttachment;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity; import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.TransportedItemStack;
import com.simibubi.create.modules.logistics.block.IBlockWithFilter;
import com.simibubi.create.modules.logistics.block.IInventoryManipulator; import com.simibubi.create.modules.logistics.block.IInventoryManipulator;
import com.simibubi.create.modules.logistics.transport.CardboardBoxEntity;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.block.HorizontalBlock; import net.minecraft.block.HorizontalBlock;
import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemStack;
import net.minecraft.state.StateContainer.Builder; import net.minecraft.state.StateContainer.Builder;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.util.math.shapes.VoxelShape;
@ -35,7 +38,8 @@ import net.minecraft.world.IWorld;
import net.minecraft.world.IWorldReader; import net.minecraft.world.IWorldReader;
import net.minecraft.world.World; import net.minecraft.world.World;
public class BeltFunnelBlock extends HorizontalBlock implements IBeltAttachment, IWithTileEntity<BeltFunnelTileEntity> { public class BeltFunnelBlock extends HorizontalBlock
implements IBeltAttachment, IWithTileEntity<BeltFunnelTileEntity>, IBlockWithFilter {
public static final VoxelShape SHAPE_NORTH = makeCuboidShape(3, -4, -1, 13, 8, 5), public static final VoxelShape SHAPE_NORTH = makeCuboidShape(3, -4, -1, 13, 8, 5),
SHAPE_SOUTH = makeCuboidShape(3, -4, 11, 13, 8, 17), SHAPE_WEST = makeCuboidShape(-1, -4, 3, 5, 8, 13), SHAPE_SOUTH = makeCuboidShape(3, -4, 11, 13, 8, 17), SHAPE_WEST = makeCuboidShape(-1, -4, 3, 5, 8, 13),
@ -43,6 +47,7 @@ public class BeltFunnelBlock extends HorizontalBlock implements IBeltAttachment,
public BeltFunnelBlock() { public BeltFunnelBlock() {
super(Properties.from(Blocks.ANDESITE)); super(Properties.from(Blocks.ANDESITE));
cacheItemPositions();
} }
@Override @Override
@ -77,6 +82,11 @@ public class BeltFunnelBlock extends HorizontalBlock implements IBeltAttachment,
public boolean isValidPosition(BlockState state, IWorldReader worldIn, BlockPos pos) { public boolean isValidPosition(BlockState state, IWorldReader worldIn, BlockPos pos) {
BlockPos neighbourPos = pos.offset(state.get(HORIZONTAL_FACING)); BlockPos neighbourPos = pos.offset(state.get(HORIZONTAL_FACING));
BlockState neighbour = worldIn.getBlockState(neighbourPos); BlockState neighbour = worldIn.getBlockState(neighbourPos);
if (AllBlocks.BELT.typeOf(neighbour)) {
return BeltBlock.canAccessFromSide(state.get(HORIZONTAL_FACING), neighbour);
}
return !neighbour.getShape(worldIn, pos).isEmpty(); return !neighbour.getShape(worldIn, pos).isEmpty();
} }
@ -138,34 +148,89 @@ public class BeltFunnelBlock extends HorizontalBlock implements IBeltAttachment,
} }
@Override @Override
public List<BlockPos> getPotentialAttachmentLocations(BeltTileEntity te) { public List<BlockPos> getPotentialAttachmentPositions(IWorld world, BlockPos pos, BlockState beltState) {
return Arrays.asList(te.getPos().up()); return Arrays.asList(pos.up());
} }
@Override @Override
public Optional<BlockPos> getValidBeltPositionFor(IWorld world, BlockPos pos, BlockState state) { public BlockPos getBeltPositionForAttachment(IWorld world, BlockPos pos, BlockState state) {
BlockPos validPos = pos.down(); return pos.down();
BlockState blockState = world.getBlockState(validPos);
if (!AllBlocks.BELT.typeOf(blockState)
|| blockState.get(HORIZONTAL_FACING).getAxis() != state.get(HORIZONTAL_FACING).getAxis())
return Optional.empty();
return Optional.of(validPos);
} }
@Override @Override
public boolean handleEntity(BeltTileEntity te, Entity entity, BeltAttachmentState state) { public boolean startProcessingItem(BeltTileEntity te, TransportedItemStack transported, BeltAttachmentState state) {
boolean isItem = entity instanceof ItemEntity; return process(te, transported, state);
if (!isItem && !(entity instanceof CardboardBoxEntity)) }
return false;
boolean slope = te.getBlockState().get(BeltBlock.SLOPE) != Slope.HORIZONTAL;
if (isItem && entity.getPositionVec().distanceTo(VecHelper.getCenterOf(te.getPos())) > (slope ? .6f : .4f))
return false;
entity.setMotion(Vec3d.ZERO);
withTileEntityDo(te.getWorld(), state.attachmentPos, funnelTE -> {
funnelTE.tryToInsert(entity);
});
@Override
public boolean processItem(BeltTileEntity te, TransportedItemStack transported, BeltAttachmentState state) {
Direction movementFacing = te.getMovementFacing();
if (movementFacing.getAxis() == Axis.Z)
movementFacing = movementFacing.getOpposite();
if (movementFacing != te.getWorld().getBlockState(state.attachmentPos)
.get(HORIZONTAL_FACING))
return false;
return process(te, transported, state);
}
public boolean process(BeltTileEntity belt, TransportedItemStack transported, BeltAttachmentState state) {
TileEntity te = belt.getWorld().getTileEntity(state.attachmentPos);
if (te == null || !(te instanceof BeltFunnelTileEntity))
return false;
BeltFunnelTileEntity funnel = (BeltFunnelTileEntity) te;
ItemStack stack = funnel.tryToInsert(transported.stack);
transported.stack = stack;
return true; return true;
} }
@Override
public boolean onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn,
BlockRayTraceResult hit) {
return handleActivatedFilterSlots(state, worldIn, pos, player, handIn, hit);
}
private static final List<Vec3d> itemPositions = new ArrayList<>(Direction.values().length);
private void cacheItemPositions() {
itemPositions.clear();
Vec3d position = Vec3d.ZERO;
Vec3d shift = VecHelper.getCenterOf(BlockPos.ZERO);
float zFightOffset = 1 / 128f;
for (int i = 0; i < 4; i++) {
Direction facing = Direction.byHorizontalIndex(i);
position = new Vec3d(8f / 16f + zFightOffset, 9f / 16f, 2.25f / 16f);
float angle = facing.getHorizontalAngle();
if (facing.getAxis() == Axis.X)
angle = -angle;
position = VecHelper.rotate(position.subtract(shift), angle, Axis.Y).add(shift);
itemPositions.add(position);
}
}
@Override
public boolean showsCount() {
return true;
}
@Override
public float getItemHitboxScale() {
return 1.76f / 16f;
}
@Override
public Vec3d getFilterPosition(BlockState state) {
Direction facing = state.get(HORIZONTAL_FACING).getOpposite();
return itemPositions.get(facing.getHorizontalIndex());
}
@Override
public Direction getFilterFacing(BlockState state) {
return state.get(HORIZONTAL_FACING).getOpposite();
}
} }

View file

@ -2,11 +2,11 @@ package com.simibubi.create.modules.logistics.block.belts;
import com.simibubi.create.AllTileEntities; import com.simibubi.create.AllTileEntities;
import com.simibubi.create.foundation.block.SyncedTileEntity; import com.simibubi.create.foundation.block.SyncedTileEntity;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.relays.belt.ItemHandlerBeltSegment;
import com.simibubi.create.modules.logistics.block.IHaveFilter;
import com.simibubi.create.modules.logistics.block.IInventoryManipulator; import com.simibubi.create.modules.logistics.block.IInventoryManipulator;
import com.simibubi.create.modules.logistics.transport.CardboardBoxEntity;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.particles.ItemParticleData; import net.minecraft.particles.ItemParticleData;
@ -16,44 +16,63 @@ import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvents; import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.Vec3i; import net.minecraft.util.math.Vec3i;
import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.items.ItemHandlerHelper;
public class BeltFunnelTileEntity extends SyncedTileEntity implements ITickableTileEntity, IInventoryManipulator { public class BeltFunnelTileEntity extends SyncedTileEntity
implements ITickableTileEntity, IInventoryManipulator, IHaveFilter {
private LazyOptional<IItemHandler> inventory; private LazyOptional<IItemHandler> inventory;
protected boolean waitingForInventorySpace; protected boolean waitingForInventorySpace;
private boolean initialize; private boolean initialize;
private ItemStack filter;
private ItemStack justEaten;
public BeltFunnelTileEntity() { public BeltFunnelTileEntity() {
super(AllTileEntities.BELT_FUNNEL.type); super(AllTileEntities.BELT_FUNNEL.type);
inventory = LazyOptional.empty(); inventory = LazyOptional.empty();
filter = ItemStack.EMPTY;
} }
@Override @Override
public void read(CompoundNBT compound) { public void read(CompoundNBT compound) {
filter = ItemStack.read(compound.getCompound("Filter"));
waitingForInventorySpace = compound.getBoolean("Waiting"); waitingForInventorySpace = compound.getBoolean("Waiting");
super.read(compound); super.read(compound);
} }
@Override
public CompoundNBT write(CompoundNBT compound) {
compound.put("Filter", filter.serializeNBT());
compound.putBoolean("Waiting", waitingForInventorySpace);
return super.write(compound);
}
@Override @Override
public void onLoad() { public void onLoad() {
initialize = true; initialize = true;
} }
@Override
public CompoundNBT writeToClient(CompoundNBT tag) {
if (justEaten != null) {
tag.put("Nom", justEaten.serializeNBT());
justEaten = null;
}
return super.writeToClient(tag);
}
@Override @Override
public void readClientUpdate(CompoundNBT tag) { public void readClientUpdate(CompoundNBT tag) {
super.readClientUpdate(tag); super.readClientUpdate(tag);
if (!waitingForInventorySpace) if (!waitingForInventorySpace)
neighborChanged(); neighborChanged();
} if (tag.contains("Nom"))
justEaten = ItemStack.read(tag.getCompound("Nom"));
@Override
public CompoundNBT write(CompoundNBT compound) {
compound.putBoolean("Waiting", waitingForInventorySpace);
return super.write(compound);
} }
@Override @Override
@ -72,6 +91,10 @@ public class BeltFunnelTileEntity extends SyncedTileEntity implements ITickableT
neighborChanged(); neighborChanged();
initialize = false; initialize = false;
} }
if (world.isRemote && justEaten != null) {
spawnParticles(justEaten);
justEaten = null;
}
} }
@Override @Override
@ -87,42 +110,57 @@ public class BeltFunnelTileEntity extends SyncedTileEntity implements ITickableT
sendData(); sendData();
} }
public void tryToInsert(Entity entity) { public ItemStack tryToInsert(ItemStack stack) {
if (!inventory.isPresent()) if (!inventory.isPresent())
return; return stack;
if (waitingForInventorySpace) if (waitingForInventorySpace && !(inventory.orElse(null) instanceof ItemHandlerBeltSegment))
return; return stack;
if (!filter.isEmpty() && !ItemStack.areItemsEqual(filter, stack))
ItemStack stack = null; return stack;
if (entity instanceof ItemEntity)
stack = ((ItemEntity) entity).getItem().copy();
if (entity instanceof CardboardBoxEntity)
stack = ((CardboardBoxEntity) entity).getBox().copy();
IItemHandler inv = inventory.orElse(null); IItemHandler inv = inventory.orElse(null);
stack = ItemHandlerHelper.insertItemStacked(inv, stack, false); ItemStack inserted = stack.copy();
int amountToExtract = Math.min(filter.isEmpty() ? 64 : filter.getCount(), stack.getCount());
inserted.setCount(amountToExtract);
if (stack.isEmpty()) { ItemStack remainder = ItemHandlerHelper.insertItemStacked(inv, inserted, false);
if (!world.isRemote) {
entity.remove(); if (remainder.isEmpty()) {
if (!world.isRemote)
world.playSound(null, pos, SoundEvents.ENTITY_GENERIC_EAT, SoundCategory.BLOCKS, .125f, 1f); world.playSound(null, pos, SoundEvents.ENTITY_GENERIC_EAT, SoundCategory.BLOCKS, .125f, 1f);
justEaten = stack.copy();
remainder = stack.copy();
remainder.setCount(stack.getCount() - amountToExtract);
} else { } else {
waitingForInventorySpace = true;
remainder.grow(stack.getCount() - amountToExtract);
}
sendData();
return remainder;
}
public void spawnParticles(ItemStack stack) {
Vec3i directionVec = getBlockState().get(BlockStateProperties.HORIZONTAL_FACING).getDirectionVec(); Vec3i directionVec = getBlockState().get(BlockStateProperties.HORIZONTAL_FACING).getDirectionVec();
float xSpeed = directionVec.getX() * 1 / 8f; float xSpeed = directionVec.getX() * 1 / 8f;
float zSpeed = directionVec.getZ() * 1 / 8f; float zSpeed = directionVec.getZ() * 1 / 8f;
world.addParticle(new ItemParticleData(ParticleTypes.ITEM, stack), entity.posX, Vec3d vec = VecHelper.getCenterOf(pos);
entity.posY, entity.posZ, xSpeed, 1 / 6f, zSpeed); world.addParticle(new ItemParticleData(ParticleTypes.ITEM, stack), vec.x, vec.y - 9 / 16f, vec.z, xSpeed,
} 1 / 6f, zSpeed);
return;
} }
waitingForInventorySpace = true; @Override
public void setFilter(ItemStack stack) {
filter = stack.copy();
markDirty();
sendData(); sendData();
neighborChanged();
}
if (entity instanceof ItemEntity) @Override
if (!stack.equals(((ItemEntity) entity).getItem(), false)) public ItemStack getFilter() {
((ItemEntity) entity).setItem(stack); return filter.copy();
} }
} }

View file

@ -0,0 +1,22 @@
package com.simibubi.create.modules.logistics.block.belts;
import com.simibubi.create.modules.logistics.block.FilteredTileEntityRenderer;
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
public class BeltFunnelTileEntityRenderer extends TileEntityRenderer<BeltFunnelTileEntity> {
FilteredTileEntityRenderer filterRenderer;
public BeltFunnelTileEntityRenderer() {
filterRenderer = new FilteredTileEntityRenderer();
}
@Override
public void render(BeltFunnelTileEntity tileEntityIn, double x, double y, double z, float partialTicks,
int destroyStage) {
super.render(tileEntityIn, x, y, z, partialTicks, destroyStage);
filterRenderer.render(tileEntityIn, x, y, z, partialTicks, destroyStage);
}
}

View file

@ -3,7 +3,6 @@ package com.simibubi.create.modules.logistics.block.belts;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.Random; import java.util.Random;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
@ -15,6 +14,7 @@ import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity; import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.TransportedItemStack;
import com.simibubi.create.modules.logistics.block.IBlockWithFilter; import com.simibubi.create.modules.logistics.block.IBlockWithFilter;
import net.minecraft.block.Block; import net.minecraft.block.Block;
@ -129,16 +129,20 @@ public class EntityDetectorBlock extends HorizontalBlock
} }
@Override @Override
public List<BlockPos> getPotentialAttachmentLocations(BeltTileEntity te) { public List<BlockPos> getPotentialAttachmentPositions(IWorld world, BlockPos pos, BlockState beltState) {
Direction side = te.getBlockState().get(BeltBlock.HORIZONTAL_FACING).rotateY(); Direction side = beltState.get(BeltBlock.HORIZONTAL_FACING).rotateY();
return Arrays.asList(te.getPos().offset(side), te.getPos().offset(side.getOpposite())); return Arrays.asList(pos.offset(side), pos.offset(side.getOpposite()));
} }
@Override @Override
public Optional<BlockPos> getValidBeltPositionFor(IWorld world, BlockPos pos, BlockState state) { public BlockPos getBeltPositionForAttachment(IWorld world, BlockPos pos, BlockState state) {
if (!state.get(BELT)) return pos.offset(state.get(HORIZONTAL_FACING));
return Optional.empty(); }
return Optional.of(pos.offset(state.get(HORIZONTAL_FACING)));
@Override
public boolean isAttachedCorrectly(IWorld world, BlockPos attachmentPos, BlockPos beltPos, BlockState attachmentState,
BlockState beltState) {
return attachmentState.get(BELT);
} }
@Override @Override
@ -178,7 +182,35 @@ public class EntityDetectorBlock extends HorizontalBlock
} }
@Override @Override
public boolean handleEntity(BeltTileEntity te, Entity entity, BeltAttachmentState state) { public boolean startProcessingItem(BeltTileEntity te, TransportedItemStack transported, BeltAttachmentState state) {
state.processingDuration = 0;
withTileEntityDo(te.getWorld(), state.attachmentPos, detectorTE -> {
ItemStack filter = detectorTE.getFilter();
if (filter.isEmpty())
return;
// Todo: Package filters
if (!ItemStack.areItemsEqual(transported.stack, filter)) {
state.processingDuration = -1;
return;
}
});
World world = te.getWorld();
BlockState blockState = world.getBlockState(state.attachmentPos);
if (state.processingDuration == 0) {
world.setBlockState(state.attachmentPos, blockState.with(POWERED, true));
world.getPendingBlockTicks().scheduleTick(state.attachmentPos, this, 6);
world.notifyNeighborsOfStateChange(state.attachmentPos, this);
return true;
}
return false;
}
@Override
public boolean processEntity(BeltTileEntity te, Entity entity, BeltAttachmentState state) {
if (te.getWorld().isRemote) if (te.getWorld().isRemote)
return false; return false;
@ -190,6 +222,8 @@ public class EntityDetectorBlock extends HorizontalBlock
ItemStack filter = detectorTE.getFilter(); ItemStack filter = detectorTE.getFilter();
if (filter.isEmpty()) if (filter.isEmpty())
return; return;
// Todo: Package filters
if (!(entity instanceof ItemEntity) if (!(entity instanceof ItemEntity)
|| !ItemStack.areItemsEqual(((ItemEntity) entity).getItem(), filter)) { || !ItemStack.areItemsEqual(((ItemEntity) entity).getItem(), filter)) {
state.processingDuration = -1; state.processingDuration = -1;

View file

@ -3,7 +3,9 @@ package com.simibubi.create.modules.logistics.block.belts;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock;
import com.simibubi.create.modules.logistics.block.IBlockWithFilter; import com.simibubi.create.modules.logistics.block.IBlockWithFilter;
import com.simibubi.create.modules.logistics.block.IExtractor; import com.simibubi.create.modules.logistics.block.IExtractor;
@ -91,8 +93,14 @@ public class ExtractorBlock extends HorizontalBlock implements IBlockWithFilter
@Override @Override
public boolean isValidPosition(BlockState state, IWorldReader worldIn, BlockPos pos) { public boolean isValidPosition(BlockState state, IWorldReader worldIn, BlockPos pos) {
BlockPos neighbourPos = pos.offset(state.get(HORIZONTAL_FACING)); Direction facing = state.get(HORIZONTAL_FACING);
BlockPos neighbourPos = pos.offset(facing);
BlockState neighbour = worldIn.getBlockState(neighbourPos); BlockState neighbour = worldIn.getBlockState(neighbourPos);
if (AllBlocks.BELT.typeOf(neighbour)) {
return BeltBlock.canAccessFromSide(facing, neighbour);
}
return !neighbour.getShape(worldIn, pos).isEmpty(); return !neighbour.getShape(worldIn, pos).isEmpty();
} }

View file

@ -1,75 +1,175 @@
{ {
"forgemarker": 1,
"defaults": {
"model": "create:block/belt/horizontal_middle"
},
"variants": { "variants": {
"slope=horizontal,part=start,facing=north": { "model": "create:block/belt/horizontal_end", "x": 0, "y": 180 }, "casing=false,slope=horizontal,part=start,facing=north": { "model": "create:block/belt/horizontal_end", "x": 0, "y": 180 },
"slope=horizontal,part=start,facing=south": { "model": "create:block/belt/horizontal_end", "x": 0, "y": 0 }, "casing=false,slope=horizontal,part=start,facing=south": { "model": "create:block/belt/horizontal_end", "x": 0, "y": 0 },
"slope=horizontal,part=start,facing=east": { "model": "create:block/belt/horizontal_end", "x": 0, "y": 270 }, "casing=false,slope=horizontal,part=start,facing=east": { "model": "create:block/belt/horizontal_end", "x": 0, "y": 270 },
"slope=horizontal,part=start,facing=west": { "model": "create:block/belt/horizontal_end", "x": 0, "y": 90 }, "casing=false,slope=horizontal,part=start,facing=west": { "model": "create:block/belt/horizontal_end", "x": 0, "y": 90 },
"slope=horizontal,part=middle,facing=north": { "model": "create:block/belt/horizontal_middle", "x": 0, "y": 180 }, "casing=false,slope=horizontal,part=middle,facing=north": { "model": "create:block/belt/horizontal_middle", "x": 0, "y": 180 },
"slope=horizontal,part=middle,facing=south": { "model": "create:block/belt/horizontal_middle", "x": 0, "y": 0 }, "casing=false,slope=horizontal,part=middle,facing=south": { "model": "create:block/belt/horizontal_middle", "x": 0, "y": 0 },
"slope=horizontal,part=middle,facing=east": { "model": "create:block/belt/horizontal_middle", "x": 0, "y": 270 }, "casing=false,slope=horizontal,part=middle,facing=east": { "model": "create:block/belt/horizontal_middle", "x": 0, "y": 270 },
"slope=horizontal,part=middle,facing=west": { "model": "create:block/belt/horizontal_middle", "x": 0, "y": 90 }, "casing=false,slope=horizontal,part=middle,facing=west": { "model": "create:block/belt/horizontal_middle", "x": 0, "y": 90 },
"slope=horizontal,part=end,facing=north": { "model": "create:block/belt/horizontal_start", "x": 0, "y": 180 }, "casing=false,slope=horizontal,part=end,facing=north": { "model": "create:block/belt/horizontal_start", "x": 0, "y": 180 },
"slope=horizontal,part=end,facing=south": { "model": "create:block/belt/horizontal_start", "x": 0, "y": 0 }, "casing=false,slope=horizontal,part=end,facing=south": { "model": "create:block/belt/horizontal_start", "x": 0, "y": 0 },
"slope=horizontal,part=end,facing=east": { "model": "create:block/belt/horizontal_start", "x": 0, "y": 270 }, "casing=false,slope=horizontal,part=end,facing=east": { "model": "create:block/belt/horizontal_start", "x": 0, "y": 270 },
"slope=horizontal,part=end,facing=west": { "model": "create:block/belt/horizontal_start", "x": 0, "y": 90 }, "casing=false,slope=horizontal,part=end,facing=west": { "model": "create:block/belt/horizontal_start", "x": 0, "y": 90 },
"casing=false,slope=horizontal,part=pulley,facing=north": { "model": "create:block/belt/horizontal_middle", "x": 0, "y": 180 },
"casing=false,slope=horizontal,part=pulley,facing=south": { "model": "create:block/belt/horizontal_middle", "x": 0, "y": 0 },
"casing=false,slope=horizontal,part=pulley,facing=east": { "model": "create:block/belt/horizontal_middle", "x": 0, "y": 270 },
"casing=false,slope=horizontal,part=pulley,facing=west": { "model": "create:block/belt/horizontal_middle", "x": 0, "y": 90 },
"casing=false,slope=vertical,part=end,facing=north": { "model": "create:block/belt/horizontal_end", "x": 90, "y": 180 },
"casing=false,slope=vertical,part=end,facing=south": { "model": "create:block/belt/horizontal_start", "x": 90, "y": 0 },
"casing=false,slope=vertical,part=end,facing=east": { "model": "create:block/belt/horizontal_start", "x": 90, "y": 270 },
"casing=false,slope=vertical,part=end,facing=west": { "model": "create:block/belt/horizontal_end", "x": 90, "y": 90 },
"casing=false,slope=vertical,part=middle,facing=north": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 180 },
"casing=false,slope=vertical,part=middle,facing=south": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 0 },
"casing=false,slope=vertical,part=middle,facing=east": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 270 },
"casing=false,slope=vertical,part=middle,facing=west": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 90 },
"casing=false,slope=vertical,part=start,facing=north": { "model": "create:block/belt/horizontal_start", "x": 90, "y": 180 },
"casing=false,slope=vertical,part=start,facing=south": { "model": "create:block/belt/horizontal_end", "x": 90, "y": 0 },
"casing=false,slope=vertical,part=start,facing=east": { "model": "create:block/belt/horizontal_end", "x": 90, "y": 270 },
"casing=false,slope=vertical,part=start,facing=west": { "model": "create:block/belt/horizontal_start", "x": 90, "y": 90 },
"casing=false,slope=vertical,part=pulley,facing=north": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 180 },
"casing=false,slope=vertical,part=pulley,facing=south": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 0 },
"casing=false,slope=vertical,part=pulley,facing=east": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 270 },
"casing=false,slope=vertical,part=pulley,facing=west": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 90 },
"casing=false,slope=upward,part=start,facing=north": { "model": "create:block/belt/downward_end", "x": 0, "y": 180 },
"casing=false,slope=upward,part=start,facing=south": { "model": "create:block/belt/downward_end", "x": 0, "y": 0 },
"casing=false,slope=upward,part=start,facing=east": { "model": "create:block/belt/downward_end", "x": 0, "y": 270 },
"casing=false,slope=upward,part=start,facing=west": { "model": "create:block/belt/downward_end", "x": 0, "y": 90 },
"casing=false,slope=upward,part=middle,facing=north": { "model": "create:block/belt/downward_middle", "x": 0, "y": 180 },
"casing=false,slope=upward,part=middle,facing=south": { "model": "create:block/belt/downward_middle", "x": 0, "y": 0 },
"casing=false,slope=upward,part=middle,facing=east": { "model": "create:block/belt/downward_middle", "x": 0, "y": 270 },
"casing=false,slope=upward,part=middle,facing=west": { "model": "create:block/belt/downward_middle", "x": 0, "y": 90 },
"casing=false,slope=upward,part=end,facing=north": { "model": "create:block/belt/downward_start", "x": 0, "y": 180 },
"casing=false,slope=upward,part=end,facing=south": { "model": "create:block/belt/downward_start", "x": 0, "y": 0 },
"casing=false,slope=upward,part=end,facing=east": { "model": "create:block/belt/downward_start", "x": 0, "y": 270 },
"casing=false,slope=upward,part=end,facing=west": { "model": "create:block/belt/downward_start", "x": 0, "y": 90 },
"casing=false,slope=upward,part=pulley,facing=north": { "model": "create:block/belt/downward_middle", "x": 0, "y": 180 },
"casing=false,slope=upward,part=pulley,facing=south": { "model": "create:block/belt/downward_middle", "x": 0, "y": 0 },
"casing=false,slope=upward,part=pulley,facing=east": { "model": "create:block/belt/downward_middle", "x": 0, "y": 270 },
"casing=false,slope=upward,part=pulley,facing=west": { "model": "create:block/belt/downward_middle", "x": 0, "y": 90 },
"casing=false,slope=downward,part=start,facing=north": { "model": "create:block/belt/upward_end", "x": 0, "y": 180 },
"casing=false,slope=downward,part=start,facing=south": { "model": "create:block/belt/upward_end", "x": 0, "y": 0 },
"casing=false,slope=downward,part=start,facing=east": { "model": "create:block/belt/upward_end", "x": 0, "y": 270 },
"casing=false,slope=downward,part=start,facing=west": { "model": "create:block/belt/upward_end", "x": 0, "y": 90 },
"casing=false,slope=downward,part=middle,facing=north": { "model": "create:block/belt/upward_middle", "x": 0, "y": 180 },
"casing=false,slope=downward,part=middle,facing=south": { "model": "create:block/belt/upward_middle", "x": 0, "y": 0 },
"casing=false,slope=downward,part=middle,facing=east": { "model": "create:block/belt/upward_middle", "x": 0, "y": 270 },
"casing=false,slope=downward,part=middle,facing=west": { "model": "create:block/belt/upward_middle", "x": 0, "y": 90 },
"casing=false,slope=downward,part=end,facing=north": { "model": "create:block/belt/upward_start", "x": 0, "y": 180 },
"casing=false,slope=downward,part=end,facing=south": { "model": "create:block/belt/upward_start", "x": 0, "y": 0 },
"casing=false,slope=downward,part=end,facing=east": { "model": "create:block/belt/upward_start", "x": 0, "y": 270 },
"casing=false,slope=downward,part=end,facing=west": { "model": "create:block/belt/upward_start", "x": 0, "y": 90 },
"casing=false,slope=downward,part=pulley,facing=north": { "model": "create:block/belt/upward_middle", "x": 0, "y": 180 },
"casing=false,slope=downward,part=pulley,facing=south": { "model": "create:block/belt/upward_middle", "x": 0, "y": 0 },
"casing=false,slope=downward,part=pulley,facing=east": { "model": "create:block/belt/upward_middle", "x": 0, "y": 270 },
"casing=false,slope=downward,part=pulley,facing=west": { "model": "create:block/belt/upward_middle", "x": 0, "y": 90 },
"slope=vertical,part=end,facing=north": { "model": "create:block/belt/horizontal_end", "x": 90, "y": 180 },
"slope=vertical,part=end,facing=south": { "model": "create:block/belt/horizontal_start", "x": 90, "y": 0 },
"slope=vertical,part=end,facing=east": { "model": "create:block/belt/horizontal_start", "x": 90, "y": 270 },
"slope=vertical,part=end,facing=west": { "model": "create:block/belt/horizontal_end", "x": 90, "y": 90 },
"slope=vertical,part=middle,facing=north": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 180 },
"slope=vertical,part=middle,facing=south": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 0 },
"slope=vertical,part=middle,facing=east": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 270 },
"slope=vertical,part=middle,facing=west": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 90 },
"slope=vertical,part=start,facing=north": { "model": "create:block/belt/horizontal_start", "x": 90, "y": 180 },
"slope=vertical,part=start,facing=south": { "model": "create:block/belt/horizontal_end", "x": 90, "y": 0 },
"slope=vertical,part=start,facing=east": { "model": "create:block/belt/horizontal_end", "x": 90, "y": 270 },
"slope=vertical,part=start,facing=west": { "model": "create:block/belt/horizontal_start", "x": 90, "y": 90 },
"slope=upward,part=start,facing=north": { "model": "create:block/belt/downward_end", "x": 0, "y": 180 }, "casing=true,slope=horizontal,part=start,facing=north": { "model": "create:block/belt/horizontal_casing_pulley", "x": 0, "y": 180 },
"slope=upward,part=start,facing=south": { "model": "create:block/belt/downward_end", "x": 0, "y": 0 }, "casing=true,slope=horizontal,part=start,facing=south": { "model": "create:block/belt/horizontal_casing_pulley", "x": 0, "y": 0 },
"slope=upward,part=start,facing=east": { "model": "create:block/belt/downward_end", "x": 0, "y": 270 }, "casing=true,slope=horizontal,part=start,facing=east": { "model": "create:block/belt/horizontal_casing_pulley", "x": 0, "y": 270 },
"slope=upward,part=start,facing=west": { "model": "create:block/belt/downward_end", "x": 0, "y": 90 }, "casing=true,slope=horizontal,part=start,facing=west": { "model": "create:block/belt/horizontal_casing_pulley", "x": 0, "y": 90 },
"slope=upward,part=middle,facing=north": { "model": "create:block/belt/downward_middle", "x": 0, "y": 180 }, "casing=true,slope=horizontal,part=middle,facing=north": { "model": "create:block/belt/horizontal_casing", "x": 0, "y": 180 },
"slope=upward,part=middle,facing=south": { "model": "create:block/belt/downward_middle", "x": 0, "y": 0 }, "casing=true,slope=horizontal,part=middle,facing=south": { "model": "create:block/belt/horizontal_casing", "x": 0, "y": 0 },
"slope=upward,part=middle,facing=east": { "model": "create:block/belt/downward_middle", "x": 0, "y": 270 }, "casing=true,slope=horizontal,part=middle,facing=east": { "model": "create:block/belt/horizontal_casing", "x": 0, "y": 270 },
"slope=upward,part=middle,facing=west": { "model": "create:block/belt/downward_middle", "x": 0, "y": 90 }, "casing=true,slope=horizontal,part=middle,facing=west": { "model": "create:block/belt/horizontal_casing", "x": 0, "y": 90 },
"slope=upward,part=end,facing=north": { "model": "create:block/belt/downward_start", "x": 0, "y": 180 }, "casing=true,slope=horizontal,part=end,facing=north": { "model": "create:block/belt/horizontal_casing_pulley", "x": 0, "y": 180 },
"slope=upward,part=end,facing=south": { "model": "create:block/belt/downward_start", "x": 0, "y": 0 }, "casing=true,slope=horizontal,part=end,facing=south": { "model": "create:block/belt/horizontal_casing_pulley", "x": 0, "y": 0 },
"slope=upward,part=end,facing=east": { "model": "create:block/belt/downward_start", "x": 0, "y": 270 }, "casing=true,slope=horizontal,part=end,facing=east": { "model": "create:block/belt/horizontal_casing_pulley", "x": 0, "y": 270 },
"slope=upward,part=end,facing=west": { "model": "create:block/belt/downward_start", "x": 0, "y": 90 }, "casing=true,slope=horizontal,part=end,facing=west": { "model": "create:block/belt/horizontal_casing_pulley", "x": 0, "y": 90 },
"casing=true,slope=horizontal,part=pulley,facing=north": { "model": "create:block/belt/horizontal_casing_pulley", "x": 0, "y": 180 },
"casing=true,slope=horizontal,part=pulley,facing=south": { "model": "create:block/belt/horizontal_casing_pulley", "x": 0, "y": 0 },
"casing=true,slope=horizontal,part=pulley,facing=east": { "model": "create:block/belt/horizontal_casing_pulley", "x": 0, "y": 270 },
"casing=true,slope=horizontal,part=pulley,facing=west": { "model": "create:block/belt/horizontal_casing_pulley", "x": 0, "y": 90 },
"casing=true,slope=upward,part=start,facing=north": { "model": "create:block/belt/diagonal_casing_bottom", "x": 0, "y": 0 },
"casing=true,slope=upward,part=start,facing=south": { "model": "create:block/belt/diagonal_casing_bottom", "x": 0, "y": 180 },
"casing=true,slope=upward,part=start,facing=east": { "model": "create:block/belt/diagonal_casing_bottom", "x": 0, "y": 90 },
"casing=true,slope=upward,part=start,facing=west": { "model": "create:block/belt/diagonal_casing_bottom", "x": 0, "y": 270 },
"slope=downward,part=start,facing=north": { "model": "create:block/belt/upward_end", "x": 0, "y": 180 }, "casing=true,slope=upward,part=middle,facing=north": { "model": "create:block/belt/diagonal_casing_middle", "x": 0, "y": 0 },
"slope=downward,part=start,facing=south": { "model": "create:block/belt/upward_end", "x": 0, "y": 0 }, "casing=true,slope=upward,part=middle,facing=south": { "model": "create:block/belt/diagonal_casing_middle", "x": 0, "y": 180 },
"slope=downward,part=start,facing=east": { "model": "create:block/belt/upward_end", "x": 0, "y": 270 }, "casing=true,slope=upward,part=middle,facing=east": { "model": "create:block/belt/diagonal_casing_middle", "x": 0, "y": 90 },
"slope=downward,part=start,facing=west": { "model": "create:block/belt/upward_end", "x": 0, "y": 90 }, "casing=true,slope=upward,part=middle,facing=west": { "model": "create:block/belt/diagonal_casing_middle", "x": 0, "y": 270 },
"slope=downward,part=middle,facing=north": { "model": "create:block/belt/upward_middle", "x": 0, "y": 180 }, "casing=true,slope=upward,part=end,facing=north": { "model": "create:block/belt/diagonal_casing_top", "x": 0, "y": 180 },
"slope=downward,part=middle,facing=south": { "model": "create:block/belt/upward_middle", "x": 0, "y": 0 }, "casing=true,slope=upward,part=end,facing=south": { "model": "create:block/belt/diagonal_casing_top", "x": 0, "y": 0 },
"slope=downward,part=middle,facing=east": { "model": "create:block/belt/upward_middle", "x": 0, "y": 270 }, "casing=true,slope=upward,part=end,facing=east": { "model": "create:block/belt/diagonal_casing_top", "x": 0, "y": 270 },
"slope=downward,part=middle,facing=west": { "model": "create:block/belt/upward_middle", "x": 0, "y": 90 }, "casing=true,slope=upward,part=end,facing=west": { "model": "create:block/belt/diagonal_casing_top", "x": 0, "y": 90 },
"slope=downward,part=end,facing=north": { "model": "create:block/belt/upward_start", "x": 0, "y": 180 }, "casing=true,slope=upward,part=pulley,facing=north": { "model": "create:block/belt/diagonal_casing_middle_pulley", "x": 0, "y": 0 },
"slope=downward,part=end,facing=south": { "model": "create:block/belt/upward_start", "x": 0, "y": 0 }, "casing=true,slope=upward,part=pulley,facing=south": { "model": "create:block/belt/diagonal_casing_middle_pulley", "x": 0, "y": 180 },
"slope=downward,part=end,facing=east": { "model": "create:block/belt/upward_start", "x": 0, "y": 270 }, "casing=true,slope=upward,part=pulley,facing=east": { "model": "create:block/belt/diagonal_casing_middle_pulley", "x": 0, "y": 90 },
"slope=downward,part=end,facing=west": { "model": "create:block/belt/upward_start", "x": 0, "y": 90 } "casing=true,slope=upward,part=pulley,facing=west": { "model": "create:block/belt/diagonal_casing_middle_pulley", "x": 0, "y": 270 },
"casing=true,slope=vertical,part=end,facing=north": { "model": "create:block/belt/horizontal_end", "x": 90, "y": 180 },
"casing=true,slope=vertical,part=end,facing=south": { "model": "create:block/belt/horizontal_start", "x": 90, "y": 0 },
"casing=true,slope=vertical,part=end,facing=east": { "model": "create:block/belt/horizontal_start", "x": 90, "y": 270 },
"casing=true,slope=vertical,part=end,facing=west": { "model": "create:block/belt/horizontal_end", "x": 90, "y": 90 },
"casing=true,slope=vertical,part=middle,facing=north": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 180 },
"casing=true,slope=vertical,part=middle,facing=south": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 0 },
"casing=true,slope=vertical,part=middle,facing=east": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 270 },
"casing=true,slope=vertical,part=middle,facing=west": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 90 },
"casing=true,slope=vertical,part=start,facing=north": { "model": "create:block/belt/horizontal_start", "x": 90, "y": 180 },
"casing=true,slope=vertical,part=start,facing=south": { "model": "create:block/belt/horizontal_end", "x": 90, "y": 0 },
"casing=true,slope=vertical,part=start,facing=east": { "model": "create:block/belt/horizontal_end", "x": 90, "y": 270 },
"casing=true,slope=vertical,part=start,facing=west": { "model": "create:block/belt/horizontal_start", "x": 90, "y": 90 },
"casing=true,slope=vertical,part=pulley,facing=north": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 180 },
"casing=true,slope=vertical,part=pulley,facing=south": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 0 },
"casing=true,slope=vertical,part=pulley,facing=east": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 270 },
"casing=true,slope=vertical,part=pulley,facing=west": { "model": "create:block/belt/horizontal_middle", "x": 90, "y": 90 },
"casing=true,slope=downward,part=start,facing=north": { "model": "create:block/belt/diagonal_casing_top", "x": 0, "y": 0 },
"casing=true,slope=downward,part=start,facing=south": { "model": "create:block/belt/diagonal_casing_top", "x": 0, "y": 180 },
"casing=true,slope=downward,part=start,facing=east": { "model": "create:block/belt/diagonal_casing_top", "x": 0, "y": 90 },
"casing=true,slope=downward,part=start,facing=west": { "model": "create:block/belt/diagonal_casing_top", "x": 0, "y": 270 },
"casing=true,slope=downward,part=middle,facing=north": { "model": "create:block/belt/diagonal_casing_middle", "x": 0, "y": 180 },
"casing=true,slope=downward,part=middle,facing=south": { "model": "create:block/belt/diagonal_casing_middle", "x": 0, "y": 0 },
"casing=true,slope=downward,part=middle,facing=east": { "model": "create:block/belt/diagonal_casing_middle", "x": 0, "y": 270 },
"casing=true,slope=downward,part=middle,facing=west": { "model": "create:block/belt/diagonal_casing_middle", "x": 0, "y": 90 },
"casing=true,slope=downward,part=end,facing=north": { "model": "create:block/belt/diagonal_casing_bottom", "x": 0, "y": 180 },
"casing=true,slope=downward,part=end,facing=south": { "model": "create:block/belt/diagonal_casing_bottom", "x": 0, "y": 0 },
"casing=true,slope=downward,part=end,facing=east": { "model": "create:block/belt/diagonal_casing_bottom", "x": 0, "y": 270 },
"casing=true,slope=downward,part=end,facing=west": { "model": "create:block/belt/diagonal_casing_bottom", "x": 0, "y": 90 },
"casing=true,slope=downward,part=pulley,facing=north": { "model": "create:block/belt/diagonal_casing_middle_pulley", "x": 0, "y": 180 },
"casing=true,slope=downward,part=pulley,facing=south": { "model": "create:block/belt/diagonal_casing_middle_pulley", "x": 0, "y": 0 },
"casing=true,slope=downward,part=pulley,facing=east": { "model": "create:block/belt/diagonal_casing_middle_pulley", "x": 0, "y": 270 },
"casing=true,slope=downward,part=pulley,facing=west": { "model": "create:block/belt/diagonal_casing_middle_pulley", "x": 0, "y": 90 }
} }
} }

View file

@ -0,0 +1,98 @@
{
"credit": "Made with Blockbench",
"parent": "block/block",
"textures": {
"particle": "create:block/brass_casing_side",
"1": "create:block/belt_support_side",
"2": "create:block/brass_casing_side",
"8": "create:block/gearbox"
},
"elements": [
{
"name": "Casing",
"from": [1.1, 5, 2],
"to": [14.9, 11, 14],
"rotation": {"angle": 45, "axis": "x", "origin": [8, 8, 8]},
"faces": {
"north": {"uv": [0, 0, 15, 6], "texture": "#1"},
"east": {"uv": [2, 5, 14, 11], "texture": "#8"},
"south": {"uv": [0, 0, 15, 6], "texture": "#1"},
"west": {"uv": [2, 5, 14, 11], "texture": "#8"}
}
},
{
"name": "Casing",
"from": [1.1, 11, 6],
"to": [14.9, 13, 10],
"rotation": {"angle": 45, "axis": "x", "origin": [8, 8, 8]},
"faces": {
"east": {"uv": [6, 3, 10, 5], "texture": "#8"},
"west": {"uv": [6, 3, 10, 5], "texture": "#8"}
}
},
{
"name": "Left",
"from": [0, 0, 0],
"to": [16, 10, 5],
"faces": {
"north": {"uv": [0, 0, 10, 16], "rotation": 90, "texture": "#2"},
"east": {"uv": [11, 1, 16, 11], "texture": "#2"},
"south": {"uv": [0, 1, 16, 11], "texture": "#2"},
"west": {"uv": [0, 1, 5, 11], "texture": "#2"},
"up": {"uv": [0, 0, 5, 16], "rotation": 90, "texture": "#2"},
"down": {"uv": [0, 0, 5, 16], "rotation": 90, "texture": "#2"}
}
},
{
"name": "Zfighter2",
"from": [0.5, 0.1, 15.1],
"to": [15.5, 11.1, 16.1],
"faces": {
"east": {"uv": [12, 0, 13, 10.8], "texture": "#2"},
"south": {"uv": [0, 0, 15, 10.8], "texture": "#2"},
"west": {"uv": [0, 0, 1, 10.8], "texture": "#2"},
"up": {"uv": [0, 0, 15, 1], "texture": "#2"},
"down": {"uv": [0, 0, 1, 15], "rotation": 90, "texture": "#2"}
}
},
{
"name": "Right",
"from": [0, 0, 11],
"to": [16, 11, 16],
"faces": {
"north": {"uv": [0, 0, 2, 11], "texture": "#2"},
"east": {"uv": [0, 0, 4, 11], "texture": "#2"},
"south": {"uv": [0, 0, 16, 11], "texture": "#2"},
"west": {"uv": [12, 0, 16, 11], "texture": "#2"},
"up": {"uv": [12, 0, 16, 16], "rotation": 90, "texture": "#2"},
"down": {"uv": [12, 0, 16, 16], "rotation": 90, "texture": "#2"}
}
},
{
"name": "Down",
"from": [0, 0, 5],
"to": [16, 5.1, 11],
"faces": {
"north": {"uv": [0, 6, 16, 11], "texture": "#2"},
"east": {"uv": [4, 5.9, 10, 11], "texture": "#2"},
"west": {"uv": [4, 5.9, 10, 11], "texture": "#2"},
"up": {"uv": [0, 2, 16, 8], "texture": "#2"},
"down": {"uv": [4, 0, 10, 16], "rotation": 90, "texture": "#2"}
}
},
{
"name": "Top Diagonal",
"from": [-0.1, 2, -3.325],
"to": [16.1, 11, 4.7],
"rotation": {"angle": 45, "axis": "x", "origin": [8, 8, 8]},
"faces": {
"north": {"uv": [7, 0, 16, 16], "rotation": 270, "texture": "#2"},
"east": {"uv": [0, 0, 8.025, 9], "texture": "#2"},
"south": {"uv": [7, 0, 16, 16], "rotation": 270, "texture": "#2"},
"west": {"uv": [0, 0, 8.025, 9], "texture": "#2"},
"up": {"uv": [0, 0, 8.025, 16], "rotation": 270, "texture": "#2"},
"down": {"uv": [0, 0, 8.025, 16], "rotation": 270, "texture": "#2"}
}
}
]
}

View file

@ -0,0 +1,74 @@
{
"credit": "Made with Blockbench",
"parent": "block/block",
"textures": {
"particle": "create:block/brass_casing_side",
"2": "create:block/brass_casing_side",
"8": "create:block/gearbox"
},
"elements": [
{
"name": "Casing",
"from": [1.1, 11, 6],
"to": [14.9, 13, 10],
"rotation": {"angle": 45, "axis": "x", "origin": [8, 8, 8]},
"faces": {
"east": {"uv": [6, 3, 10, 5], "texture": "#8"},
"west": {"uv": [6, 3, 10, 5], "texture": "#8"}
}
},
{
"name": "Left",
"from": [0, 0, 0],
"to": [16, 10, 5],
"faces": {
"north": {"uv": [0, 0, 10, 16], "rotation": 90, "texture": "#2"},
"east": {"uv": [11, 1, 16, 11], "texture": "#2"},
"south": {"uv": [0, 1, 16, 11], "texture": "#2"},
"west": {"uv": [0, 1, 5, 11], "texture": "#2"},
"up": {"uv": [0, 0, 5, 16], "rotation": 90, "texture": "#2"},
"down": {"uv": [0, 0, 5, 16], "rotation": 90, "texture": "#2"}
}
},
{
"name": "Down",
"from": [0, 0, 5],
"to": [16, 5.1, 11],
"faces": {
"north": {"uv": [0, 6, 16, 11], "texture": "#2"},
"east": {"uv": [4, 5.9, 10, 11], "texture": "#2"},
"west": {"uv": [4, 5.9, 10, 11], "texture": "#2"},
"up": {"uv": [0, 2, 16, 8], "texture": "#2"},
"down": {"uv": [4, 0, 10, 16], "rotation": 90, "texture": "#2"}
}
},
{
"name": "Top Diagonal",
"from": [-0.1, 2, -3.325],
"to": [16.1, 11, 10],
"rotation": {"angle": 45, "axis": "x", "origin": [8, 8, 8]},
"faces": {
"north": {"uv": [7, 0, 16, 16], "rotation": 270, "texture": "#2"},
"east": {"uv": [0, 0, 13.325, 9], "texture": "#2"},
"south": {"uv": [7, 0, 16, 16], "rotation": 270, "texture": "#2"},
"west": {"uv": [0, 0, 8.025, 9], "texture": "#2"},
"up": {"uv": [0, 0, 8.025, 16], "rotation": 270, "texture": "#2"},
"down": {"uv": [0, 0, 8.025, 16], "rotation": 270, "texture": "#2"}
}
},
{
"name": "Top Diagonal",
"from": [-0.1, 2, 10],
"to": [16.1, 11, 19.3],
"rotation": {"angle": 45, "axis": "x", "origin": [8, 8, 8]},
"faces": {
"north": {"uv": [7, 0, 16, 16], "rotation": 270, "texture": "#2"},
"east": {"uv": [0, 0, 9.3, 9], "texture": "#2"},
"south": {"uv": [7, 0, 16, 16], "rotation": 270, "texture": "#2"},
"west": {"uv": [0, 0, 9.3, 9], "texture": "#2"},
"up": {"uv": [0, 0, 8.025, 16], "rotation": 270, "texture": "#2"},
"down": {"uv": [0, 0, 8.025, 16], "rotation": 270, "texture": "#2"}
}
}
]
}

View file

@ -0,0 +1,87 @@
{
"credit": "Made with Blockbench",
"parent": "block/block",
"textures": {
"particle": "create:block/brass_casing_side",
"1": "create:block/belt_support_side",
"2": "create:block/brass_casing_side",
"8": "create:block/gearbox"
},
"elements": [
{
"name": "Casing",
"from": [1.1, 5, 2],
"to": [14.9, 11, 14],
"rotation": {"angle": 45, "axis": "x", "origin": [8, 8, 8]},
"faces": {
"north": {"uv": [0, 0, 15, 6], "texture": "#1"},
"east": {"uv": [2, 5, 14, 11], "texture": "#8"},
"south": {"uv": [0, 0, 15, 6], "texture": "#1"},
"west": {"uv": [2, 5, 14, 11], "texture": "#8"}
}
},
{
"name": "Casing",
"from": [1.1, 11, 6],
"to": [14.9, 13, 10],
"rotation": {"angle": 45, "axis": "x", "origin": [8, 8, 8]},
"faces": {
"east": {"uv": [6, 3, 10, 5], "texture": "#8"},
"west": {"uv": [6, 3, 10, 5], "texture": "#8"}
}
},
{
"name": "Left",
"from": [0, 0, 0],
"to": [16, 10, 5],
"faces": {
"north": {"uv": [0, 0, 10, 16], "rotation": 90, "texture": "#2"},
"east": {"uv": [11, 1, 16, 11], "texture": "#2"},
"south": {"uv": [0, 1, 16, 11], "texture": "#2"},
"west": {"uv": [0, 1, 5, 11], "texture": "#2"},
"up": {"uv": [0, 0, 5, 16], "rotation": 90, "texture": "#2"},
"down": {"uv": [0, 0, 5, 16], "rotation": 90, "texture": "#2"}
}
},
{
"name": "Down",
"from": [0, 0, 5],
"to": [16, 5.1, 11],
"faces": {
"north": {"uv": [0, 6, 16, 11], "texture": "#2"},
"east": {"uv": [4, 5.9, 10, 11], "texture": "#2"},
"west": {"uv": [4, 5.9, 10, 11], "texture": "#2"},
"up": {"uv": [0, 2, 16, 8], "texture": "#2"},
"down": {"uv": [4, 0, 10, 16], "rotation": 90, "texture": "#2"}
}
},
{
"name": "Top Diagonal",
"from": [-0.1, 2, -3.325],
"to": [16.1, 11, 4.7],
"rotation": {"angle": 45, "axis": "x", "origin": [8, 8, 8]},
"faces": {
"north": {"uv": [7, 0, 16, 16], "rotation": 270, "texture": "#2"},
"east": {"uv": [0, 0, 8.025, 9], "texture": "#2"},
"south": {"uv": [7, 0, 16, 16], "rotation": 270, "texture": "#2"},
"west": {"uv": [0, 0, 8.025, 9], "texture": "#2"},
"up": {"uv": [0, 0, 8.025, 16], "rotation": 270, "texture": "#2"},
"down": {"uv": [0, 0, 8.025, 16], "rotation": 270, "texture": "#2"}
}
},
{
"name": "Top Diagonal",
"from": [-0.1, 2, 11.275],
"to": [16.1, 11, 19.3],
"rotation": {"angle": 45, "axis": "x", "origin": [8, 8, 8]},
"faces": {
"north": {"uv": [7, 0, 16, 16], "rotation": 270, "texture": "#2"},
"east": {"uv": [0, 0, 8.025, 9], "texture": "#2"},
"south": {"uv": [7, 0, 16, 16], "rotation": 270, "texture": "#2"},
"west": {"uv": [0, 0, 8.025, 9], "texture": "#2"},
"up": {"uv": [0, 0, 8.025, 16], "rotation": 270, "texture": "#2"},
"down": {"uv": [0, 0, 8.025, 16], "rotation": 270, "texture": "#2"}
}
}
]
}

View file

@ -0,0 +1,86 @@
{
"credit": "Made with Blockbench",
"parent": "block/block",
"textures": {
"particle": "create:block/brass_casing_side",
"1": "create:block/belt_support_side",
"2": "create:block/brass_casing_side",
"8": "create:block/gearbox"
},
"elements": [
{
"name": "Casing",
"from": [1.1, 4, 4],
"to": [14.9, 11, 14],
"rotation": {"angle": 45, "axis": "x", "origin": [8, 8, 8]},
"faces": {
"north": {"uv": [0, 0, 15, 6], "texture": "#1"},
"east": {"uv": [2, 5, 12, 12], "texture": "#8"},
"south": {"uv": [0, 0, 15, 6], "texture": "#1"},
"west": {"uv": [4, 5, 14, 12], "texture": "#8"}
}
},
{
"name": "Casing",
"from": [1.1, 11, 6],
"to": [14.9, 13, 10],
"rotation": {"angle": 45, "axis": "x", "origin": [8, 8, 8]},
"faces": {
"east": {"uv": [6, 3, 10, 5], "texture": "#8"},
"west": {"uv": [6, 3, 10, 5], "texture": "#8"}
}
},
{
"name": "Zfighter2",
"from": [0.5, 0.1, 15.1],
"to": [15.5, 11.1, 16.1],
"faces": {
"east": {"uv": [12, 0, 13, 10.8], "texture": "#2"},
"south": {"uv": [0, 0, 15, 10.8], "texture": "#2"},
"west": {"uv": [0, 0, 1, 10.8], "texture": "#2"},
"up": {"uv": [0, 0, 15, 1], "texture": "#2"},
"down": {"uv": [0, 0, 1, 15], "rotation": 90, "texture": "#2"}
}
},
{
"name": "Right",
"from": [0, 0, 11],
"to": [16, 11, 16],
"faces": {
"north": {"uv": [0, 0, 2, 11], "texture": "#2"},
"east": {"uv": [0, 0, 4, 11], "texture": "#2"},
"south": {"uv": [0, 0, 16, 11], "texture": "#2"},
"west": {"uv": [12, 0, 16, 11], "texture": "#2"},
"up": {"uv": [12, 0, 16, 16], "rotation": 90, "texture": "#2"},
"down": {"uv": [12, 0, 16, 16], "rotation": 90, "texture": "#2"}
}
},
{
"name": "Down",
"from": [0, 0, 5],
"to": [16, 5.1, 11],
"faces": {
"north": {"uv": [0, 6, 16, 11], "texture": "#2"},
"east": {"uv": [4, 5.9, 10, 11], "texture": "#2"},
"south": {"uv": [0, 0, 16, 5], "texture": "#missing"},
"west": {"uv": [4, 5.9, 10, 11], "texture": "#2"},
"up": {"uv": [0, 2, 16, 8], "texture": "#2"},
"down": {"uv": [4, 0, 10, 16], "rotation": 90, "texture": "#2"}
}
},
{
"name": "Top Diagonal",
"from": [-0.1, 2, -3.328],
"to": [16.1, 11, 4.697],
"rotation": {"angle": -45, "axis": "x", "origin": [8, 8, 8]},
"faces": {
"north": {"uv": [7, 0, 16, 16], "rotation": 270, "texture": "#2"},
"east": {"uv": [0, 0, 8.025, 9], "texture": "#2"},
"south": {"uv": [7, 0, 16, 16], "rotation": 270, "texture": "#2"},
"west": {"uv": [0, 0, 8.025, 9], "texture": "#2"},
"up": {"uv": [0, 0, 8.025, 16], "rotation": 270, "texture": "#2"},
"down": {"uv": [0, 0, 8.025, 16], "rotation": 270, "texture": "#2"}
}
}
]
}

View file

@ -0,0 +1,24 @@
{
"credit": "Made with Blockbench",
"parent": "block/block",
"textures": {
"particle": "create:block/brass_casing_side",
"1": "create:block/belt_support_side",
"2": "create:block/brass_casing_side"
},
"elements": [
{
"name": "Casing",
"from": [0, 0, 0],
"to": [16, 11, 16],
"faces": {
"north": {"uv": [0, 0, 16, 11], "texture": "#1"},
"east": {"uv": [0, 0, 16, 11], "texture": "#2"},
"south": {"uv": [0, 0, 16, 11], "texture": "#1"},
"west": {"uv": [0, 0, 16, 11], "texture": "#2"},
"up": {"uv": [0, 0, 16, 16], "rotation": 90, "texture": "#2"},
"down": {"uv": [0, 0, 16, 16], "rotation": 90, "texture": "#2"}
}
}
]
}

View file

@ -0,0 +1,84 @@
{
"credit": "Made with Blockbench",
"parent": "block/block",
"textures": {
"particle": "create:block/brass_casing_side",
"1": "create:block/belt_support_side",
"2": "create:block/brass_casing_side",
"8": "create:block/gearbox"
},
"elements": [
{
"name": "Casing",
"from": [1, 5, 2],
"to": [15, 11, 14],
"faces": {
"north": {"uv": [0, 0, 15, 6], "texture": "#1"},
"east": {"uv": [2, 5, 14, 11], "texture": "#8"},
"south": {"uv": [0, 0, 15, 6], "texture": "#1"},
"west": {"uv": [2, 5, 14, 11], "texture": "#8"}
}
},
{
"name": "Left",
"from": [0, 0, 0],
"to": [16, 11, 4],
"faces": {
"north": {"uv": [0, 0, 16, 11], "texture": "#2"},
"east": {"uv": [12, 0, 16, 11], "texture": "#2"},
"south": {"uv": [14, 0, 16, 11], "texture": "#2"},
"west": {"uv": [0, 0, 4, 11], "texture": "#2"},
"up": {"uv": [0, 0, 4, 16], "rotation": 90, "texture": "#2"},
"down": {"uv": [0, 0, 4, 16], "rotation": 90, "texture": "#2"}
}
},
{
"name": "Zfighter",
"from": [0.5, 0.1, -0.1],
"to": [15.5, 10.9, 0.9],
"faces": {
"north": {"uv": [0, 0, 15, 10.8], "texture": "#2"},
"east": {"uv": [12, 0, 13, 10.8], "texture": "#2"},
"west": {"uv": [0, 0, 1, 10.8], "texture": "#2"},
"up": {"uv": [0, 0, 15, 1], "texture": "#2"},
"down": {"uv": [0, 0, 1, 15], "rotation": 90, "texture": "#2"}
}
},
{
"name": "Zfighter2",
"from": [0.5, 0.1, 15.1],
"to": [15.5, 10.9, 16.1],
"faces": {
"east": {"uv": [12, 0, 13, 10.8], "texture": "#2"},
"south": {"uv": [0, 0, 15, 10.8], "texture": "#2"},
"west": {"uv": [0, 0, 1, 10.8], "texture": "#2"},
"up": {"uv": [0, 0, 15, 1], "texture": "#2"},
"down": {"uv": [0, 0, 1, 15], "rotation": 90, "texture": "#2"}
}
},
{
"name": "Right",
"from": [0, 0, 12],
"to": [16, 11, 16],
"faces": {
"north": {"uv": [0, 0, 2, 11], "texture": "#2"},
"east": {"uv": [0, 0, 4, 11], "texture": "#2"},
"south": {"uv": [0, 0, 16, 11], "texture": "#2"},
"west": {"uv": [12, 0, 16, 11], "texture": "#2"},
"up": {"uv": [12, 0, 16, 16], "rotation": 90, "texture": "#2"},
"down": {"uv": [12, 0, 16, 16], "rotation": 90, "texture": "#2"}
}
},
{
"name": "Down",
"from": [0, 0, 4],
"to": [16, 4, 12],
"faces": {
"east": {"uv": [4, 7, 12, 11], "texture": "#2"},
"west": {"uv": [4, 7, 12, 11], "texture": "#2"},
"up": {"uv": [0, 2, 16, 10], "texture": "#2"},
"down": {"uv": [4, 0, 12, 16], "rotation": 90, "texture": "#2"}
}
}
]
}

View file

@ -1,8 +1,8 @@
{ {
"__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)", "credit": "Made with Blockbench",
"textures": { "textures": {
"particle": "create:block/belt_funnel",
"belt_funnel": "create:block/belt_funnel", "belt_funnel": "create:block/belt_funnel",
"particle": "create:block/belt_funnel",
"brass_casing": "create:block/brass_casing" "brass_casing": "create:block/brass_casing"
}, },
"elements": [ "elements": [
@ -11,12 +11,12 @@
"from": [3, -4.1, -1], "from": [3, -4.1, -1],
"to": [13, -3.1, 5], "to": [13, -3.1, 5],
"faces": { "faces": {
"north": { "texture": "#belt_funnel", "uv": [ 0, 11, 10, 12 ] }, "north": {"uv": [0, 11, 10, 12], "texture": "#belt_funnel"},
"east": { "texture": "#belt_funnel", "uv": [ 10, 11, 16, 12 ] }, "east": {"uv": [10, 11, 16, 12], "texture": "#belt_funnel"},
"south": { "texture": "#belt_funnel", "uv": [ 0, 11, 10, 12 ] }, "south": {"uv": [0, 11, 10, 12], "texture": "#belt_funnel"},
"west": { "texture": "#belt_funnel", "uv": [ 10, 11, 16, 12 ], "rotation": 180 }, "west": {"uv": [10, 11, 16, 12], "rotation": 180, "texture": "#belt_funnel"},
"up": { "texture": "#belt_funnel", "uv": [ 10, 0, 16, 13 ], "rotation": 90 }, "up": {"uv": [10, 0, 16, 13], "rotation": 90, "texture": "#belt_funnel"},
"down": { "texture": "#belt_funnel", "uv": [ 10, 0, 16, 12 ], "rotation": 90 } "down": {"uv": [10, 1, 16, 11], "rotation": 90, "texture": "#belt_funnel"}
} }
}, },
{ {
@ -24,12 +24,12 @@
"from": [3, 7, -1], "from": [3, 7, -1],
"to": [13, 8, 5], "to": [13, 8, 5],
"faces": { "faces": {
"north": { "texture": "#belt_funnel", "uv": [ 0, 0, 10, 1 ] }, "north": {"uv": [0, 0, 10, 1], "texture": "#belt_funnel"},
"east": { "texture": "#belt_funnel", "uv": [ 10, 0, 16, 1 ] }, "east": {"uv": [10, 0, 16, 1], "texture": "#belt_funnel"},
"south": { "texture": "#belt_funnel", "uv": [ 0, 0, 10, 1 ] }, "south": {"uv": [0, 0, 10, 1], "texture": "#belt_funnel"},
"west": { "texture": "#belt_funnel", "uv": [ 10, 0, 16, 1 ], "rotation": 180 }, "west": {"uv": [10, 0, 16, 1], "rotation": 180, "texture": "#belt_funnel"},
"up": { "texture": "#belt_funnel", "uv": [ 10, 0, 16, 12 ], "rotation": 90 }, "up": {"uv": [10, 1, 16, 11], "rotation": 90, "texture": "#belt_funnel"},
"down": { "texture": "#belt_funnel", "uv": [ 10, 0, 16, 13 ], "rotation": 90 } "down": {"uv": [10, 0, 16, 13], "rotation": 90, "texture": "#belt_funnel"}
} }
}, },
{ {
@ -37,10 +37,10 @@
"from": [3, -3.1, -1], "from": [3, -3.1, -1],
"to": [4, 7, 5], "to": [4, 7, 5],
"faces": { "faces": {
"north": { "texture": "#belt_funnel", "uv": [ 9, 1, 10, 11.1 ] }, "north": {"uv": [9, 1, 10, 11.1], "texture": "#belt_funnel"},
"east": { "texture": "#belt_funnel", "uv": [ 10, 1, 16, 11 ] }, "east": {"uv": [10, 1, 16, 11], "texture": "#belt_funnel"},
"south": { "texture": "#belt_funnel", "uv": [ 0, 1, 1, 11.1 ] }, "south": {"uv": [0, 1, 1, 11.1], "texture": "#belt_funnel"},
"west": { "texture": "#belt_funnel", "uv": [ 10, 1, 16, 11 ] } "west": {"uv": [10, 1, 16, 11], "texture": "#belt_funnel"}
} }
}, },
{ {
@ -48,36 +48,47 @@
"from": [4, -3.1, -1], "from": [4, -3.1, -1],
"to": [12, 7, 4], "to": [12, 7, 4],
"faces": { "faces": {
"north": { "texture": "#brass_casing", "uv": [ 4, 3, 12, 13.1 ] }, "north": {"uv": [4, 3, 12, 13.1], "texture": "#brass_casing"},
"east": { "texture": "#belt_funnel", "uv": [ 9, 3, 10, 9 ], "rotation": 90 }, "east": {"uv": [9, 3, 10, 9], "rotation": 90, "texture": "#belt_funnel"},
"south": { "texture": "#belt_funnel", "uv": [ 1, 1, 9, 11.1 ] }, "south": {"uv": [1, 1, 9, 11.1], "texture": "#belt_funnel"},
"west": { "texture": "#belt_funnel", "uv": [ 0, 2, 1, 8 ], "rotation": 90 } "west": {"uv": [0, 2, 1, 8], "rotation": 90, "texture": "#belt_funnel"}
} }
}, },
{ {
"name": "Top", "name": "Top",
"from": [ 4, 6, 0 ], "from": [4, 9, -1],
"to": [ 12, 8, 4.8 ], "to": [12, 10, 4.25],
"rotation": { "origin": [ 8, 8, 0 ], "axis": "x", "angle": -22.5 }, "rotation": {"angle": 22.5, "axis": "x", "origin": [8, 8, 0]},
"faces": { "faces": {
"north": { "texture": "#belt_funnel", "uv": [ 1, 7, 9, 9 ], "rotation": 180 }, "north": {"uv": [1, 12, 9, 13], "rotation": 180, "texture": "#belt_funnel"},
"east": { "texture": "#belt_funnel", "uv": [ 11, 4.6, 16, 6.6 ], "rotation": 180 }, "east": {"uv": [10, 5, 16, 6], "rotation": 180, "texture": "#belt_funnel"},
"south": { "texture": "#belt_funnel", "uv": [ 9, 2, 11, 10 ], "rotation": 90 }, "south": {"uv": [9, 2, 11, 10], "rotation": 90, "texture": "#belt_funnel"},
"west": { "texture": "#belt_funnel", "uv": [ 10, 5, 15, 7.4 ], "rotation": 180 }, "west": {"uv": [10, 5, 16, 6], "texture": "#belt_funnel"},
"up": { "texture": "#belt_funnel", "uv": [ 11, 2, 16, 9.4 ], "rotation": 90 }, "up": {"uv": [10, 2, 16, 10], "rotation": 90, "texture": "#belt_funnel"},
"down": { "texture": "#belt_funnel", "uv": [ 1, 8, 9, 12.8 ] } "down": {"uv": [1, 8, 9, 12.8], "texture": "#belt_funnel"}
}
},
{
"name": "Top",
"from": [4, 7, -1],
"to": [12, 9, 2.5],
"rotation": {"angle": 22.5, "axis": "x", "origin": [8, 8, 0]},
"faces": {
"north": {"uv": [1, 11, 9, 13], "texture": "#belt_funnel"},
"east": {"uv": [10, 5, 14, 7], "rotation": 180, "texture": "#belt_funnel"},
"west": {"uv": [10, 5, 14, 6], "texture": "#belt_funnel"}
} }
}, },
{ {
"name": "Ramp", "name": "Ramp",
"from": [4, -4, -8], "from": [4, -4, -8],
"to": [12, 3, -1], "to": [12, 3, -1],
"rotation": { "origin": [ 8, -4, -1 ], "axis": "x", "angle": 45.0 }, "rotation": {"angle": 45, "axis": "x", "origin": [8, -4, -1]},
"faces": { "faces": {
"north": { "texture": "#brass_casing", "uv": [ 4, 5, 12, 12 ] }, "north": {"uv": [4, 5, 12, 12], "texture": "#brass_casing"},
"east": { "texture": "#brass_casing", "uv": [ 4, 9, 11, 16 ], "rotation": 90 }, "east": {"uv": [4, 9, 11, 16], "rotation": 90, "texture": "#brass_casing"},
"west": { "texture": "#brass_casing", "uv": [ 5, 9, 12, 16 ], "rotation": 270 }, "west": {"uv": [5, 9, 12, 16], "rotation": 270, "texture": "#brass_casing"},
"down": { "texture": "#brass_casing", "uv": [ 4, 0, 12, 7 ] } "down": {"uv": [4, 0, 12, 7], "texture": "#brass_casing"}
} }
}, },
{ {
@ -85,11 +96,45 @@
"from": [12, -3.1, -1], "from": [12, -3.1, -1],
"to": [13, 7, 5], "to": [13, 7, 5],
"faces": { "faces": {
"north": { "texture": "#belt_funnel", "uv": [ 0, 1, 1, 11.1 ] }, "north": {"uv": [0, 1, 1, 11.1], "texture": "#belt_funnel"},
"east": { "texture": "#belt_funnel", "uv": [ 10, 1, 16, 11 ], "rotation": 180 }, "east": {"uv": [10, 1, 16, 11], "rotation": 180, "texture": "#belt_funnel"},
"south": { "texture": "#belt_funnel", "uv": [ 9, 1, 10, 11.1 ] }, "south": {"uv": [9, 1, 10, 11.1], "texture": "#belt_funnel"},
"west": { "texture": "#belt_funnel", "uv": [ 10, 1, 16, 11 ] } "west": {"uv": [10, 1, 16, 11], "texture": "#belt_funnel"}
}
}
],
"display": {
"thirdperson_righthand": {
"rotation": [75, -149, 0],
"translation": [-0.5, 3.25, 2.25],
"scale": [0.375, 0.375, 0.375]
},
"thirdperson_lefthand": {
"rotation": [75, -149, 0],
"translation": [-0.5, 3.25, 2.25],
"scale": [0.375, 0.375, 0.375]
},
"firstperson_righthand": {
"rotation": [0, -55, 0],
"scale": [0.4, 0.4, 0.4]
},
"firstperson_lefthand": {
"rotation": [0, -55, 0],
"scale": [0.4, 0.4, 0.4]
},
"ground": {
"translation": [0, 0, 2.25],
"scale": [0.25, 0.25, 0.25]
},
"gui": {
"rotation": [30, 45, 0],
"translation": [2.5, 1.75, 0],
"scale": [0.625, 0.625, 0.625]
},
"fixed": {
"rotation": [0, 180, 0],
"translation": [0, 3.5, -4.5],
"scale": [0.5, 0.5, 0.5]
} }
} }
]
} }

View file

@ -1,7 +1,8 @@
{ {
"__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)", "credit": "Made with Blockbench",
"parent": "block/block", "parent": "block/block",
"textures": { "textures": {
"1": "create:block/brass_casing",
"extractor": "create:block/extractor", "extractor": "create:block/extractor",
"particle": "create:block/extractor" "particle": "create:block/extractor"
}, },
@ -11,11 +12,12 @@
"from": [4, 2, -1], "from": [4, 2, -1],
"to": [12, 3, 5], "to": [12, 3, 5],
"faces": { "faces": {
"east": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ], "rotation": 180 }, "north": {"uv": [6, 7, 14, 8], "texture": "#extractor"},
"south": { "texture": "#extractor", "uv": [ 6, 7, 14, 8 ] }, "east": {"uv": [0, 0, 6, 1], "rotation": 180, "texture": "#extractor"},
"west": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ] }, "south": {"uv": [6, 7, 14, 8], "texture": "#extractor"},
"up": { "texture": "#extractor", "uv": [ 9, 0, 15, 8 ], "rotation": 90 }, "west": {"uv": [0, 0, 6, 1], "texture": "#extractor"},
"down": { "texture": "#extractor", "uv": [ 0, 0, 6, 8 ], "rotation": 270 } "up": {"uv": [0, 0, 6, 8], "rotation": 90, "texture": "#extractor"},
"down": {"uv": [0, 0, 6, 8], "rotation": 270, "texture": "#extractor"}
} }
}, },
{ {
@ -23,11 +25,12 @@
"from": [4, 9, -1], "from": [4, 9, -1],
"to": [12, 10, 5], "to": [12, 10, 5],
"faces": { "faces": {
"east": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ], "rotation": 180 }, "north": {"uv": [6, 0, 14, 1], "texture": "#extractor"},
"south": { "texture": "#extractor", "uv": [ 6, 0, 14, 1 ] }, "east": {"uv": [0, 0, 6, 1], "rotation": 180, "texture": "#extractor"},
"west": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ] }, "south": {"uv": [6, 0, 14, 1], "texture": "#extractor"},
"up": { "texture": "#extractor", "uv": [ 0, 0, 6, 8 ], "rotation": 90 }, "west": {"uv": [0, 0, 6, 1], "texture": "#extractor"},
"down": { "texture": "#extractor", "uv": [ 9, 0, 15, 8 ], "rotation": 270 } "up": {"uv": [0, 0, 6, 8], "rotation": 90, "texture": "#extractor"},
"down": {"uv": [0, 0, 6, 8], "rotation": 270, "texture": "#extractor"}
} }
}, },
{ {
@ -35,9 +38,10 @@
"from": [4, 3, -1], "from": [4, 3, -1],
"to": [5, 9, 5], "to": [5, 9, 5],
"faces": { "faces": {
"east": { "texture": "#extractor", "uv": [ 9, 1, 15, 7 ], "rotation": 180 }, "north": {"uv": [13, 1, 14, 7], "texture": "#extractor"},
"south": { "texture": "#extractor", "uv": [ 6, 1, 7, 7 ] }, "east": {"uv": [0, 1, 6, 7], "rotation": 180, "texture": "#extractor"},
"west": { "texture": "#extractor", "uv": [ 0, 1, 6, 7 ] } "south": {"uv": [6, 1, 7, 7], "texture": "#extractor"},
"west": {"uv": [0, 1, 6, 7], "texture": "#extractor"}
} }
}, },
{ {
@ -45,31 +49,67 @@
"from": [11, 3, -1], "from": [11, 3, -1],
"to": [12, 9, 5], "to": [12, 9, 5],
"faces": { "faces": {
"east": { "texture": "#extractor", "uv": [ 0, 1, 6, 7 ], "rotation": 180 }, "north": {"uv": [6, 1, 7, 7], "texture": "#extractor"},
"south": { "texture": "#extractor", "uv": [ 13, 1, 14, 7 ] }, "east": {"uv": [0, 1, 6, 7], "rotation": 180, "texture": "#extractor"},
"west": { "texture": "#extractor", "uv": [ 9, 1, 15, 7 ] } "south": {"uv": [13, 1, 14, 7], "texture": "#extractor"},
"west": {"uv": [0, 1, 6, 7], "texture": "#extractor"}
} }
}, },
{ {
"name": "Center", "name": "Center",
"from": [ 5, 3, 3 ], "from": [5, 3, 0],
"to": [11, 9, 4], "to": [11, 9, 4],
"faces": { "faces": {
"south": { "texture": "#extractor", "uv": [ 7, 1, 13, 7 ] } "north": {"uv": [5, 5, 11, 11], "texture": "#1"},
"south": {"uv": [7, 1, 13, 7], "texture": "#extractor"}
} }
}, },
{ {
"name": "FilterSpot", "name": "FilterSpot",
"from": [5, 10, -0.6], "from": [5, 10, -0.6],
"to": [11, 12, 4], "to": [11, 12, 4],
"rotation": { "origin": [ 8, 11, -1 ], "axis": "x", "angle": 22.5 }, "rotation": {"angle": 22.5, "axis": "x", "origin": [8, 11, -1]},
"faces": { "faces": {
"north": { "texture": "#extractor", "uv": [ 13, 1, 15, 7 ], "rotation": 90 }, "north": {"uv": [13, 1, 15, 7], "rotation": 90, "texture": "#extractor"},
"east": { "texture": "#extractor", "uv": [ 0.1, 0, 4.7, 2 ], "rotation": 180 }, "east": {"uv": [0.1, 0, 4.7, 2], "rotation": 180, "texture": "#extractor"},
"south": { "texture": "#extractor", "uv": [ 4, 1, 5, 7 ], "rotation": 270 }, "south": {"uv": [4, 1, 5, 7], "rotation": 270, "texture": "#extractor"},
"west": { "texture": "#extractor", "uv": [ 0.1, 0, 4.7, 2 ] }, "west": {"uv": [0.1, 0, 4.7, 2], "texture": "#extractor"},
"up": { "texture": "#extractor", "uv": [ 0, 9, 5, 15 ], "rotation": 90 } "up": {"uv": [0, 9, 5, 15], "rotation": 90, "texture": "#extractor"}
}
}
],
"display": {
"thirdperson_righthand": {
"rotation": [75, -149, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"thirdperson_lefthand": {
"rotation": [75, -149, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"firstperson_righthand": {
"rotation": [0, -55, 0],
"scale": [0.4, 0.4, 0.4]
},
"firstperson_lefthand": {
"rotation": [0, -55, 0],
"scale": [0.4, 0.4, 0.4]
},
"ground": {
"translation": [0, 1, 1.25],
"scale": [0.25, 0.25, 0.25]
},
"gui": {
"rotation": [30, 45, 0],
"translation": [2.5, -0.5, 0],
"scale": [0.625, 0.625, 0.625]
},
"fixed": {
"rotation": [0, 180, 0],
"translation": [0, 1.75, -4.5],
"scale": [0.5, 0.5, 0.5]
} }
} }
]
} }

View file

@ -1,7 +1,8 @@
{ {
"__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)", "credit": "Made with Blockbench",
"parent": "block/block", "parent": "create:block/extractor",
"textures": { "textures": {
"2": "create:block/brass_casing",
"redstone_antenna": "create:block/redstone_antenna", "redstone_antenna": "create:block/redstone_antenna",
"extractor": "create:block/extractor", "extractor": "create:block/extractor",
"particle": "create:block/extractor" "particle": "create:block/extractor"
@ -12,11 +13,12 @@
"from": [4, 2, -1], "from": [4, 2, -1],
"to": [12, 3, 5], "to": [12, 3, 5],
"faces": { "faces": {
"east": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ], "rotation": 180 }, "north": {"uv": [6, 7, 14, 8], "texture": "#extractor"},
"south": { "texture": "#extractor", "uv": [ 6, 7, 14, 8 ] }, "east": {"uv": [0, 0, 6, 1], "rotation": 180, "texture": "#extractor"},
"west": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ] }, "south": {"uv": [6, 7, 14, 8], "texture": "#extractor"},
"up": { "texture": "#extractor", "uv": [ 9, 0, 15, 8 ], "rotation": 90 }, "west": {"uv": [0, 0, 6, 1], "texture": "#extractor"},
"down": { "texture": "#extractor", "uv": [ 0, 0, 6, 8 ], "rotation": 270 } "up": {"uv": [0, 0, 6, 8], "rotation": 90, "texture": "#extractor"},
"down": {"uv": [0, 0, 6, 8], "rotation": 270, "texture": "#extractor"}
} }
}, },
{ {
@ -24,11 +26,12 @@
"from": [4, 9, -1], "from": [4, 9, -1],
"to": [12, 10, 5], "to": [12, 10, 5],
"faces": { "faces": {
"east": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ], "rotation": 180 }, "north": {"uv": [6, 0, 14, 1], "texture": "#extractor"},
"south": { "texture": "#extractor", "uv": [ 6, 0, 14, 1 ] }, "east": {"uv": [0, 0, 6, 1], "rotation": 180, "texture": "#extractor"},
"west": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ] }, "south": {"uv": [6, 0, 14, 1], "texture": "#extractor"},
"up": { "texture": "#extractor", "uv": [ 0, 0, 6, 8 ], "rotation": 90 }, "west": {"uv": [0, 0, 6, 1], "texture": "#extractor"},
"down": { "texture": "#extractor", "uv": [ 9, 0, 15, 8 ], "rotation": 270 } "up": {"uv": [0, 0, 6, 8], "rotation": 90, "texture": "#extractor"},
"down": {"uv": [0, 0, 6, 8], "rotation": 270, "texture": "#extractor"}
} }
}, },
{ {
@ -36,9 +39,10 @@
"from": [4, 3, -1], "from": [4, 3, -1],
"to": [5, 9, 5], "to": [5, 9, 5],
"faces": { "faces": {
"east": { "texture": "#extractor", "uv": [ 9, 1, 15, 7 ], "rotation": 180 }, "north": {"uv": [13, 1, 14, 7], "texture": "#extractor"},
"south": { "texture": "#extractor", "uv": [ 6, 1, 7, 7 ] }, "east": {"uv": [0, 1, 6, 7], "rotation": 180, "texture": "#extractor"},
"west": { "texture": "#extractor", "uv": [ 0, 1, 6, 7 ] } "south": {"uv": [6, 1, 7, 7], "texture": "#extractor"},
"west": {"uv": [0, 1, 6, 7], "texture": "#extractor"}
} }
}, },
{ {
@ -46,30 +50,32 @@
"from": [11, 3, -1], "from": [11, 3, -1],
"to": [12, 9, 5], "to": [12, 9, 5],
"faces": { "faces": {
"east": { "texture": "#extractor", "uv": [ 0, 1, 6, 7 ], "rotation": 180 }, "north": {"uv": [6, 1, 7, 7], "texture": "#extractor"},
"south": { "texture": "#extractor", "uv": [ 13, 1, 14, 7 ] }, "east": {"uv": [0, 1, 6, 7], "rotation": 180, "texture": "#extractor"},
"west": { "texture": "#extractor", "uv": [ 9, 1, 15, 7 ] } "south": {"uv": [13, 1, 14, 7], "texture": "#extractor"},
"west": {"uv": [0, 1, 6, 7], "texture": "#extractor"}
} }
}, },
{ {
"name": "Center", "name": "Center",
"from": [ 5, 3, 3 ], "from": [5, 3, 0],
"to": [11, 9, 4], "to": [11, 9, 4],
"faces": { "faces": {
"south": { "texture": "#extractor", "uv": [ 7, 1, 13, 7 ] } "north": {"uv": [5, 5, 11, 11], "texture": "#2"},
"south": {"uv": [7, 1, 13, 7], "texture": "#extractor"}
} }
}, },
{ {
"name": "FilterSpot", "name": "FilterSpot",
"from": [5, 10, -0.6], "from": [5, 10, -0.6],
"to": [11, 12, 4], "to": [11, 12, 4],
"rotation": { "origin": [ 8, 11, -1 ], "axis": "x", "angle": 22.5 }, "rotation": {"angle": 22.5, "axis": "x", "origin": [8, 11, -1]},
"faces": { "faces": {
"north": { "texture": "#extractor", "uv": [ 13, 1, 15, 7 ], "rotation": 90 }, "north": {"uv": [13, 1, 15, 7], "rotation": 90, "texture": "#extractor"},
"east": { "texture": "#extractor", "uv": [ 0.1, 0, 4.7, 2 ], "rotation": 180 }, "east": {"uv": [0.1, 0, 4.7, 2], "rotation": 180, "texture": "#extractor"},
"south": { "texture": "#extractor", "uv": [ 4, 1, 5, 7 ], "rotation": 270 }, "south": {"uv": [4, 1, 5, 7], "rotation": 270, "texture": "#extractor"},
"west": { "texture": "#extractor", "uv": [ 0.1, 0, 4.7, 2 ] }, "west": {"uv": [0.1, 0, 4.7, 2], "texture": "#extractor"},
"up": { "texture": "#extractor", "uv": [ 0, 9, 5, 15 ], "rotation": 90 } "up": {"uv": [0, 9, 5, 15], "rotation": 90, "texture": "#extractor"}
} }
}, },
{ {
@ -77,9 +83,9 @@
"from": [11, 7, 2], "from": [11, 7, 2],
"to": [14, 17, 3], "to": [14, 17, 3],
"faces": { "faces": {
"north": { "texture": "#redstone_antenna", "uv": [ 0, 0, 3, 10 ] }, "north": {"uv": [0, 0, 3, 10], "texture": "#redstone_antenna"},
"south": { "texture": "#redstone_antenna", "uv": [ 0, 0, 3, 10 ] }, "south": {"uv": [0, 0, 3, 10], "texture": "#redstone_antenna"},
"down": { "texture": "#redstone_antenna", "uv": [ 0, 9, 3, 10 ] } "down": {"uv": [0, 9, 3, 10], "texture": "#redstone_antenna"}
} }
}, },
{ {
@ -87,8 +93,8 @@
"from": [12, 7, 1], "from": [12, 7, 1],
"to": [13, 17, 4], "to": [13, 17, 4],
"faces": { "faces": {
"east": { "texture": "#redstone_antenna", "uv": [ 0, 0, 3, 10 ] }, "east": {"uv": [0, 0, 3, 10], "texture": "#redstone_antenna"},
"west": { "texture": "#redstone_antenna", "uv": [ 0, 0, 3, 10 ] } "west": {"uv": [0, 0, 3, 10], "texture": "#redstone_antenna"}
} }
}, },
{ {
@ -96,7 +102,7 @@
"from": [12, 15, 2], "from": [12, 15, 2],
"to": [13, 16, 3], "to": [13, 16, 3],
"faces": { "faces": {
"up": { "texture": "#redstone_antenna", "uv": [ 1, 1, 2, 2 ] } "up": {"uv": [1, 1, 2, 2], "texture": "#redstone_antenna"}
} }
}, },
{ {
@ -104,8 +110,8 @@
"from": [10, 13, 0], "from": [10, 13, 0],
"to": [15, 13, 5], "to": [15, 13, 5],
"faces": { "faces": {
"up": { "texture": "#redstone_antenna", "uv": [ 4, 0, 9, 5 ] }, "up": {"uv": [4, 0, 9, 5], "texture": "#redstone_antenna"},
"down": { "texture": "#redstone_antenna", "uv": [ 4, 0, 9, 5 ] } "down": {"uv": [4, 0, 9, 5], "texture": "#redstone_antenna"}
} }
} }
] ]

View file

@ -1,86 +1,3 @@
{ {
"parent": "block/block", "parent": "create:block/extractor"
"display": {
"gui": {
"rotation": [ 30, 45, 0 ],
"translation": [ 0, 0, 0],
"scale":[ 0.625, 0.625, 0.625 ]
},
"fixed": {
"rotation": [ 0, 180, 0 ],
"translation": [ 0, 0, -3.5],
"scale":[ 0.5, 0.5, 0.5 ]
}
},
"textures": {
"extractor": "create:block/extractor",
"particle": "create:block/extractor"
},
"elements": [
{
"name": "Bottom",
"from": [ 4, 2, -1 ],
"to": [ 12, 3, 5 ],
"faces": {
"east": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ], "rotation": 180 },
"south": { "texture": "#extractor", "uv": [ 6, 7, 14, 8 ] },
"west": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ] },
"up": { "texture": "#extractor", "uv": [ 9, 0, 15, 8 ], "rotation": 90 },
"down": { "texture": "#extractor", "uv": [ 0, 0, 6, 8 ], "rotation": 270 }
}
},
{
"name": "Top",
"from": [ 4, 9, -1 ],
"to": [ 12, 10, 5 ],
"faces": {
"east": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ], "rotation": 180 },
"south": { "texture": "#extractor", "uv": [ 6, 0, 14, 1 ] },
"west": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ] },
"up": { "texture": "#extractor", "uv": [ 0, 0, 6, 8 ], "rotation": 90 },
"down": { "texture": "#extractor", "uv": [ 9, 0, 15, 8 ], "rotation": 270 }
}
},
{
"name": "Side",
"from": [ 4, 3, -1 ],
"to": [ 5, 9, 5 ],
"faces": {
"east": { "texture": "#extractor", "uv": [ 9, 1, 15, 7 ], "rotation": 180 },
"south": { "texture": "#extractor", "uv": [ 6, 1, 7, 7 ] },
"west": { "texture": "#extractor", "uv": [ 0, 1, 6, 7 ] }
}
},
{
"name": "Side",
"from": [ 11, 3, -1 ],
"to": [ 12, 9, 5 ],
"faces": {
"east": { "texture": "#extractor", "uv": [ 0, 1, 6, 7 ], "rotation": 180 },
"south": { "texture": "#extractor", "uv": [ 13, 1, 14, 7 ] },
"west": { "texture": "#extractor", "uv": [ 9, 1, 15, 7 ] }
}
},
{
"name": "Center",
"from": [ 5, 3, 3 ],
"to": [ 11, 9, 4 ],
"faces": {
"south": { "texture": "#extractor", "uv": [ 7, 1, 13, 7 ] }
}
},
{
"name": "FilterSpot",
"from": [ 5, 10, -0.6 ],
"to": [ 11, 12, 4 ],
"rotation": { "origin": [ 8, 11, -1 ], "axis": "x", "angle": 22.5 },
"faces": {
"north": { "texture": "#extractor", "uv": [ 13, 1, 15, 7 ], "rotation": 90 },
"east": { "texture": "#extractor", "uv": [ 0.1, 0, 4.7, 2 ], "rotation": 180 },
"south": { "texture": "#extractor", "uv": [ 4, 1, 5, 7 ], "rotation": 270 },
"west": { "texture": "#extractor", "uv": [ 0.1, 0, 4.7, 2 ] },
"up": { "texture": "#extractor", "uv": [ 0, 9, 5, 15 ], "rotation": 90 }
}
}
]
} }

View file

@ -1,123 +1,3 @@
{ {
"parent": "block/block", "parent": "create:block/extractor_wireless"
"display": {
"gui": {
"rotation": [ 30, 45, 0 ],
"translation": [ 0, 0, 0],
"scale":[ 0.625, 0.625, 0.625 ]
},
"fixed": {
"rotation": [ 0, 180, 0 ],
"translation": [ 0, 0, -3.5],
"scale":[ 0.5, 0.5, 0.5 ]
}
},
"textures": {
"redstone_antenna": "create:block/redstone_antenna",
"extractor": "create:block/extractor",
"particle": "create:block/extractor"
},
"elements": [
{
"name": "Bottom",
"from": [ 4, 2, -1 ],
"to": [ 12, 3, 5 ],
"faces": {
"east": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ], "rotation": 180 },
"south": { "texture": "#extractor", "uv": [ 6, 7, 14, 8 ] },
"west": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ] },
"up": { "texture": "#extractor", "uv": [ 9, 0, 15, 8 ], "rotation": 90 },
"down": { "texture": "#extractor", "uv": [ 0, 0, 6, 8 ], "rotation": 270 }
}
},
{
"name": "Top",
"from": [ 4, 9, -1 ],
"to": [ 12, 10, 5 ],
"faces": {
"east": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ], "rotation": 180 },
"south": { "texture": "#extractor", "uv": [ 6, 0, 14, 1 ] },
"west": { "texture": "#extractor", "uv": [ 0, 0, 6, 1 ] },
"up": { "texture": "#extractor", "uv": [ 0, 0, 6, 8 ], "rotation": 90 },
"down": { "texture": "#extractor", "uv": [ 9, 0, 15, 8 ], "rotation": 270 }
}
},
{
"name": "Side",
"from": [ 4, 3, -1 ],
"to": [ 5, 9, 5 ],
"faces": {
"east": { "texture": "#extractor", "uv": [ 9, 1, 15, 7 ], "rotation": 180 },
"south": { "texture": "#extractor", "uv": [ 6, 1, 7, 7 ] },
"west": { "texture": "#extractor", "uv": [ 0, 1, 6, 7 ] }
}
},
{
"name": "Side",
"from": [ 11, 3, -1 ],
"to": [ 12, 9, 5 ],
"faces": {
"east": { "texture": "#extractor", "uv": [ 0, 1, 6, 7 ], "rotation": 180 },
"south": { "texture": "#extractor", "uv": [ 13, 1, 14, 7 ] },
"west": { "texture": "#extractor", "uv": [ 9, 1, 15, 7 ] }
}
},
{
"name": "Center",
"from": [ 5, 3, 3 ],
"to": [ 11, 9, 4 ],
"faces": {
"south": { "texture": "#extractor", "uv": [ 7, 1, 13, 7 ] }
}
},
{
"name": "FilterSpot",
"from": [ 5, 10, -0.6 ],
"to": [ 11, 12, 4 ],
"rotation": { "origin": [ 8, 11, -1 ], "axis": "x", "angle": 22.5 },
"faces": {
"north": { "texture": "#extractor", "uv": [ 13, 1, 15, 7 ], "rotation": 90 },
"east": { "texture": "#extractor", "uv": [ 0.1, 0, 4.7, 2 ], "rotation": 180 },
"south": { "texture": "#extractor", "uv": [ 4, 1, 5, 7 ], "rotation": 270 },
"west": { "texture": "#extractor", "uv": [ 0.1, 0, 4.7, 2 ] },
"up": { "texture": "#extractor", "uv": [ 0, 9, 5, 15 ], "rotation": 90 }
}
},
{
"name": "AntennaX",
"from": [ 11, 7, 2 ],
"to": [ 14, 17, 3 ],
"faces": {
"north": { "texture": "#redstone_antenna", "uv": [ 0, 0, 3, 10 ] },
"south": { "texture": "#redstone_antenna", "uv": [ 0, 0, 3, 10 ] },
"down": { "texture": "#redstone_antenna", "uv": [ 0, 9, 3, 10 ] }
}
},
{
"name": "AntennaZ",
"from": [ 12, 7, 1 ],
"to": [ 13, 17, 4 ],
"faces": {
"east": { "texture": "#redstone_antenna", "uv": [ 0, 0, 3, 10 ] },
"west": { "texture": "#redstone_antenna", "uv": [ 0, 0, 3, 10 ] }
}
},
{
"name": "AntennaTop",
"from": [ 12, 15, 2 ],
"to": [ 13, 16, 3 ],
"faces": {
"up": { "texture": "#redstone_antenna", "uv": [ 1, 1, 2, 2 ] }
}
},
{
"name": "AntennaDish",
"from": [ 10, 13, 0 ],
"to": [ 15, 13, 5 ],
"faces": {
"up": { "texture": "#redstone_antenna", "uv": [ 4, 0, 9, 5 ] },
"down": { "texture": "#redstone_antenna", "uv": [ 4, 0, 9, 5 ] }
}
}
]
} }

View file

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

View file

@ -1,8 +1,6 @@
{ {
"replace": false, "replace": false,
"values": [ "values": [
"create:belt",
"create:crushing_wheel",
"create:limestone_wall", "create:limestone_wall",
"create:limestone_bricks_wall", "create:limestone_bricks_wall",
"create:weathered_limestone_wall", "create:weathered_limestone_wall",